{"title":"Jinja2 Template Injection via render_template_string","language":"Python","severity":"Critical","cwe":"CWE-1336","source_lines":[9,10],"flow_lines":[9,11,12],"sink_lines":[12],"vulnerable_code":"from flask import Flask, request, render_template_string\nimport boto3\n\niot_app = Flask(__name__)\ns3_client = boto3.client('s3')\n\n@iot_app.route('/device/status')\ndef fetch_device_telemetry():\n    device_id = request.args.get('device_id', 'unknown')\n    sensor_type = request.args.get('sensor', 'temperature')\n    template_markup = f\"<h2>Device {device_id} - Sensor: {sensor_type}</h2><p>Status: {{{{ status }}}}</p>\"\n    return render_template_string(template_markup, status='operational')","explanation":"The application accepts untrusted user input from request parameters (device_id and sensor_type) and directly embeds them into a Jinja2 template string via an f-string. This template is then rendered using render_template_string(), allowing attackers to inject malicious Jinja2 expressions that execute arbitrary Python code on the server.","remediation":"The fix removes the f-string interpolation that embedded user input directly into the template string. Instead, user-provided values (device_id and sensor_type) are passed as context variables to render_template_string(), which automatically escapes them via Jinja2's autoescaping, preventing any injected template expressions from being interpreted.","secure_code":"from flask import Flask, request, render_template_string\nfrom markupsafe import escape\nimport boto3\n\niot_app = Flask(__name__)\ns3_client = boto3.client('s3')\n\n@iot_app.route('/device/status')\ndef fetch_device_telemetry():\n    device_id = request.args.get('device_id', 'unknown')\n    sensor_type = request.args.get('sensor', 'temperature')\n    template_markup = \"<h2>Device {{ device_id }} - Sensor: {{ sensor_type }}</h2><p>Status: {{ status }}</p>\"\n    return render_template_string(template_markup, device_id=device_id, sensor_type=sensor_type, status='operational')"}