{"title":"Jinja2 Server-Side Template Injection via Untrusted Template Rendering","language":"Python","severity":"Critical","cwe":"CWE-1336","source_lines":[8,9],"flow_lines":[8,10,11],"sink_lines":[11],"vulnerable_code":"from jinja2 import Environment\nfrom flask import Flask, request\n\napp = Flask(__name__)\n\n@app.route('/iot/device/status')\ndef render_device_status():\n    device_id = request.args.get('device_id', 'unknown')\n    status_msg = request.args.get('message', 'Device operational')\n    template_str = f\"<h2>IoT Device: {device_id}</h2><p>Status: {status_msg}</p>\"\n    env = Environment()\n    compiled = env.from_string(template_str)\n    return compiled.render()","explanation":"User-controlled input from request.args.get() is directly interpolated into a Jinja2 template string using f-string formatting. When env.from_string() compiles and renders this template, attackers can inject Jinja2 template expressions that execute arbitrary Python code on the server.","remediation":"The fix eliminates the SSTI vulnerability by using Jinja2 template placeholders ({{ device_id }}, {{ status_msg }}) instead of f-string interpolation to pass user input into the template. User-controlled values are passed as context variables to the render() method, ensuring they are treated as data rather than template code. Additionally, autoescape=True is enabled to prevent XSS attacks.","secure_code":"from jinja2 import Environment\nfrom flask import Flask, request\nfrom markupsafe import escape\n\napp = Flask(__name__)\n\n@app.route('/iot/device/status')\ndef render_device_status():\n    device_id = request.args.get('device_id', 'unknown')\n    status_msg = request.args.get('message', 'Device operational')\n    template_str = \"<h2>IoT Device: {{ device_id }}</h2><p>Status: {{ status_msg }}</p>\"\n    env = Environment(autoescape=True)\n    compiled = env.from_string(template_str)\n    return compiled.render(device_id=device_id, status_msg=status_msg)"}