{"title":"Server-Side Template Injection via Jinja2 render_template_string","language":"Python","severity":"Critical","cwe":"CWE-1336","source_lines":[9],"flow_lines":[9,10,12],"sink_lines":[12],"vulnerable_code":"from flask import Flask, request, render_template_string\nimport boto3\n\napp = Flask(__name__)\ns3_client = boto3.client('s3')\n\n@app.route('/cloud/bucket-status')\ndef check_bucket_health():\n    bucket_name = request.args.get('bucket', 'default-bucket')\n    custom_msg = request.args.get('status_msg', 'Operational')\n    s3_response = s3_client.list_objects_v2(Bucket=bucket_name, MaxKeys=5)\n    obj_count = s3_response.get('KeyCount', 0)\n    dashboard_html = f\"<html><body><h2>AWS S3 Bucket Monitor</h2><p>Bucket: {bucket_name}</p><p>Objects: {obj_count}</p><div>Status: {custom_msg}</div></body></html>\"\n    return render_template_string(dashboard_html)","explanation":"The application accepts user-controlled input via the 'status_msg' parameter and directly embeds it into an HTML template string that is then processed by render_template_string(). This allows attackers to inject Jinja2 template expressions that will be executed server-side, leading to Remote Code Execution.","remediation":"The fix passes user-controlled variables as context parameters to render_template_string() instead of embedding them directly into the template string via f-string interpolation. Jinja2 automatically escapes variables passed through the template context using {{ }} syntax, preventing any injected template expressions from being interpreted as code.","secure_code":"from flask import Flask, request, render_template_string\nimport boto3\nfrom markupsafe import escape\n\napp = Flask(__name__)\ns3_client = boto3.client('s3')\n\n@app.route('/cloud/bucket-status')\ndef check_bucket_health():\n    bucket_name = request.args.get('bucket', 'default-bucket')\n    custom_msg = request.args.get('status_msg', 'Operational')\n    s3_response = s3_client.list_objects_v2(Bucket=bucket_name, MaxKeys=5)\n    obj_count = s3_response.get('KeyCount', 0)\n    dashboard_html = \"<html><body><h2>AWS S3 Bucket Monitor</h2><p>Bucket: {{ bucket_name }}</p><p>Objects: {{ obj_count }}</p><div>Status: {{ custom_msg }}</div></body></html>\"\n    return render_template_string(dashboard_html, bucket_name=bucket_name, obj_count=obj_count, custom_msg=custom_msg)"}