JSON Injection

ID

python.json_injection

Severity

high

Resource

Injection

Language

Python

Tags

CWE:116, NIST.SP.800-53, OWASP:2021:A3, PCI-DSS:6.5.1

Description

JSON Injection occurs when untrusted input is inserted into a JSON structure without proper validation or sanitization, allowing an attacker to manipulate or inject arbitrary JSON content. This can lead to unauthorized data exposure, privilege escalation, or denial of service.

Rationale

JSON Injection (CWE-116) arises when applications build JSON data structures by concatenating or formatting strings that include unsanitized user input, rather than using proper data structures or serialization methods. In Python, this frequently happens when developers manually construct JSON strings instead of using libraries like json or jwt safely.

Consider the following vulnerable example, where user input is directly embedded into a JSON string using string interpolation:

from flask import Flask, request, Response

app = Flask(name)

@app.route("/user")
def user():
    username = request.args.get("name", "guest")
    # Vulnerable: directly embedding user input into JSON string
    response = f'{{"user": "{username}"}}'
    return Response(response, mimetype="application/json")

If an attacker sends a specially crafted input such as:

foo", "is_admin": true, "extra": "data

The resulting JSON becomes:

{"user": "foo", "is_admin": true, "extra": "data"}

which injects unauthorized fields into the JSON response. This manipulation can bypass authorization controls or confuse JSON parsers consuming this data.

Another common scenario is with JWT tokens, where the payload is constructed insecurely from unsanitized input, allowing attackers to escalate privileges by injecting roles or flags.

Remediation

To prevent JSON Injection vulnerabilities in Python:

  1. Avoid manual JSON string construction with untrusted input. Always use safe data structures like dictionaries or objects, then serialize using trusted libraries like json.dumps().

  2. Validate and sanitize all user input. Ensure input conforms to expected formats before incorporating it into JSON payloads.

  3. For JWT payloads, build dictionaries directly instead of parsing strings. Example:

@app.route("/token")
def token():
    username = request.args.get("name", "guest")
    payload = {"user": username}

    tkn = jwt.encode(payload, SECRET, algorithm="HS256")

    return jsonify({"token": tkn})

Configuration

The detector has the following configurable parameters:

  • sources, that indicates the source kinds to check.

  • neutralizations, that indicates the neutralization kinds to check.