# Jinja2 Template Injection via render_template_string()

Language: Python
Severity: Critical
CWE: CWE-1336

## Source
9

## Flow
9-10-11

## Sink
11

## Vulnerable Code
```python
from flask import Flask, request, render_template_string
import boto3

app = Flask(__name__)
s3_client = boto3.client('s3')

@app.route('/cloud/bucket-report')
def generate_bucket_report():
    bucket_name = request.args.get('bucket', 'default-bucket')
    report_format = request.args.get('format', 'html')
    user_header = request.args.get('header', 'S3 Bucket Report')
    template_str = f"<html><head><title>{user_header}</title></head><body><h1>{user_header}</h1><p>Bucket: {bucket_name}</p><p>Format: {report_format}</p></body></html>"
    return render_template_string(template_str)
```

## Explanation

The application accepts user-controlled input from the 'header' parameter and directly interpolates it into a template string that is then passed to render_template_string(). This allows attackers to inject Jinja2 template expressions that will be executed on the server, leading to remote code execution.

## Remediation

Instead of using Python f-string interpolation to embed user input directly into the template string, the fix uses Jinja2's native variable substitution with {{ }} placeholders and passes user inputs as context variables to render_template_string(). Jinja2 automatically escapes these context variables when rendering, preventing both template injection and XSS attacks.

## Secure Code
```python
from flask import Flask, request, render_template_string
import boto3
from markupsafe import escape

app = Flask(__name__)
s3_client = boto3.client('s3')

@app.route('/cloud/bucket-report')
def generate_bucket_report():
    bucket_name = request.args.get('bucket', 'default-bucket')
    report_format = request.args.get('format', 'html')
    user_header = request.args.get('header', 'S3 Bucket Report')
    template_str = "<html><head><title>{{ header }}</title></head><body><h1>{{ header }}</h1><p>Bucket: {{ bucket }}</p><p>Format: {{ fmt }}</p></body></html>"
    return render_template_string(template_str, header=user_header, bucket=bucket_name, fmt=report_format)
```
