Xml External Entities in Gin
How Xml External Entities Manifests in Gin
XML External Entity (XXE) injection in Go APIs built with the Gin framework occurs when user-supplied XML input is processed by an XML parser that is configured to resolve external entities. Gin does not provide its own XML parser; it relies on standard library packages such as encoding/xml or third-party libraries. If an application uses features like external general entities, parameter entities, or DOCTYPE declarations, an attacker can craft XML that references local or remote resources (e.g., file:///etc/passwd) or internal services reachable from the server. Common Gin code paths include HTTP handlers that call xml.NewDecoder(req.Body).Decode(&payload) without disabling external entity resolution. For example, an endpoint that accepts XML configuration or document uploads may be vulnerable if the decoder is not explicitly secured. Attack patterns include reading arbitrary files via the file:// scheme, SSRF through entity expansion to internal endpoints, and in some environments, remote code execution via malicious DTDs. Gin routes that parse XML without disabling DTDs and entity resolution expose the unauthenticated attack surface that middleBrick tests as part of its XML/DTD and SSRF checks. Since Gin applications often sit behind load balancers or reverse proxies, network-based XXE can pivot to internal metadata services or other microservices, amplifying the impact within a containerized or cloud environment.
Gin-Specific Detection
Detecting XXE in Gin APIs requires inspecting how XML input is handled. Look for handlers that use xml.NewDecoder or third-party XML libraries without applying security hardening. A Gin route like the following is risky:
func UploadXML(c *gin.Context) {
var data map[string]interface{}
if err := xml.NewDecoder(c.Request.Body).Decode(&data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, data)
}
Without disabling external entity processing, this handler can be exploited. To detect this during scanning, use the middleBrick CLI to test the unauthenticated attack surface: middlebrick scan https://your-api.example.com. middleBrick runs parallel security checks, including XML/DTD and SSRF probes, and maps findings to frameworks like OWASP API Top 10 and provides prioritized remediation guidance in its report. In the dashboard, you can track the security score over time and, if you have the Pro plan, enforce CI/CD gates so that a build fails if the risk score exceeds your configured threshold. The scan completes in 5–15 seconds and does not require credentials, making it ideal for early detection during development or staging.
Gin-Specific Remediation
Remediation focuses on disabling external entity and DTD resolution in the XML parser. The standard library’s xml.Decoder can be secured by replacing the default Entity and CharsetReader behavior or by using a restricted parser. One approach is to use xml.NewDecoder with a custom Entity that rejects external entities:
func NewSecureXMLDecoder(r io.Reader) *xml.Decoder {
decoder := xml.NewDecoder(r)
decoder.Entity = xml.HTMLEntity
return decoder
}
func UploadXMLSecure(c *gin.Context) {
var data map[string]interface{}
if err := NewSecureXMLDecoder(c.Request.Body).Decode(&data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, data)
}
Alternatively, use a well-maintained third-party library that defaults to secure parsing, such as github.com/clbanning/mxj/v2, which provides map-based XML handling without enabling DTD resolution:
func UploadWithMXJ(c *gin.Context) {
xmlMap, err := mxj.NewMapXmlReader(c.Request.Body)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, xmlMap)
}
These patterns avoid loading external DTDs and prevent the decoder from resolving external entities. In production, combine this with input validation and strict Content-Type requirements to ensure only expected XML structures are accepted. middleBrick’s findings include specific remediation guidance, and with the Pro plan you can integrate these fixes into automated CI/CD checks using the GitHub Action to prevent vulnerable configurations from reaching production.