JSON Injection
ID |
go.json_injection |
Severity |
high |
Resource |
Injection |
Language |
Go |
Tags |
CWE:116, NIST.SP.800-53, OWASP:2021:A3, PCI-DSS:6.5.1 |
Description
Improper handling of untrusted data in JSON contexts can lead to injection vulnerabilities, allowing attackers to manipulate JSON structure or inject executable scripts if the output is used insecurely in client-side environments.
Rationale
When user-controlled input is embedded directly into JSON structures without proper validation or encoding, it can lead to JSON injection. In Go, the encoding/json
package correctly escapes most special characters, but misuse or unsafe client-side rendering can still create XSS vectors or logic manipulation issues.
A common misuse is when developers concatenate strings into JSON responses rather than fully relying on structured marshaling, or when the response is consumed by browsers or JavaScript engines that might interpret it unsafely.
Consider the following vulnerable code:
func vulnerableHandler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
resp := map[string]string{
"message": "Hello " + name,
}
jsonBytes, _ := json.Marshal(resp)
w.Header().Set("Content-Type", "application/json")
w.Write(jsonBytes)
}
If a user provides a malicious input like </script><script>alert(1)</script>
, the resulting JSON would be:
{
"message": "Hello </script><script>alert(1)</script>"
}
While json.Marshal
escapes dangerous characters, if this response is later injected into an HTML page (e.g., via innerHTML
), it can lead to XSS. Additionally, logic-based JSON injections are possible if inputs are poorly validated and parsed downstream.
Remediation
-
Never construct JSON via string concatenation — always use
json.Marshal
or similar structured serializers. -
Validate and sanitize user inputs before embedding them in any response, especially if the data will eventually be used in client-side scripts or HTML.
-
Ensure proper content-type headers are always used:
w.Header().Set("Content-Type", "application/json")
-
Avoid rendering JSON directly into HTML without escaping. If the JSON is embedded into a script or DOM, escape it properly or deliver it via XHR/fetch with strict CSP headers.
-
Prepend JSON responses with a non-executable prefix (optional):
w.Write([]byte(")]}',\n"))
This technique helps prevent JSON responses from being executable in certain browser contexts.
-
Apply security headers such as:
-
Content-Security-Policy
-
X-Content-Type-Options: nosniff
-
These reduce the browser’s ability to interpret JSON as anything other than data.