Weakness reference
CWE-644

Improper Neutralization of HTTP Headers for Scripting Syntax

This weakness occurs when an application accepts user-controlled data in HTTP headers and passes it to a downstream component such as a template engine…

01Summary

This weakness occurs when an application accepts user-controlled data in HTTP headers and passes it to a downstream component (such as a template engine, JavaScript interpreter, or HTML renderer) without properly sanitizing it first. An attacker can inject scripting syntax into headers, which the downstream component then interprets as code rather than plain text, leading to unintended execution.

02How It Happens

HTTP headers are often treated as "trusted" input because they come from the client's browser or network layer. However, headers can be manipulated by an attacker just like query parameters or form fields. When an application reads a header value (such as User-Agent, Referer, X-Custom-Header, or Accept-Language) and passes it directly into a context where scripting syntax is interpreted—such as embedding it in a template, logging it to a page, or passing it to a JavaScript engine—the attacker's injected code can execute. The vulnerability is especially dangerous when the header value is reflected back to the user in an HTTP response without encoding.

03Real-World Impact

Successful exploitation can lead to cross-site scripting (XSS) attacks, where an attacker injects JavaScript that runs in a victim's browser. This can result in session hijacking, credential theft, malware distribution, or defacement. In some cases, if headers are processed server-side by a template engine or scripting language, the impact could extend to remote code execution or information disclosure.

04Vulnerable & Fixed Patterns

Vulnerable pattern
from flask import Flask, request, render_template_string

app = Flask(__name__)

@app.route('/profile')
def profile():
    user_agent = request.headers.get('User-Agent', 'Unknown')
    # Directly embedding header value into template
    html = f"<p>Your browser: {user_agent}</p>"
    return render_template_string(html)

Why it's vulnerable:
The User-Agent header is read directly and embedded into an HTML template string without encoding. An attacker can craft a request with a malicious User-Agent header containing script tags or event handlers, which will be rendered as executable code in the response.

Fixed pattern
from flask import Flask, request, render_template_string
from markupsafe import escape

app = Flask(__name__)

@app.route('/profile')
def profile():
    user_agent = request.headers.get('User-Agent', 'Unknown')
    # Properly escape the header value before embedding
    safe_user_agent = escape(user_agent)
    html = f"<p>Your browser: {safe_user_agent}</p>"
    return render_template_string(html)
Vulnerable pattern
<?php
$custom_header = $_SERVER['HTTP_X_CUSTOM_HEADER'] ?? 'default';
// Directly embedding header into output
echo "<div class='info'>Custom value: " . $custom_header . "</div>";
?>

Why it's vulnerable:
The custom HTTP header is read from the $_SERVER superglobal and echoed directly into HTML without any encoding. An attacker can inject HTML or JavaScript through the header, which will execute in the browser.

Fixed pattern
<?php
$custom_header = $_SERVER['HTTP_X_CUSTOM_HEADER'] ?? 'default';
// Properly escape the header value for HTML context
echo "<div class='info'>Custom value: " . esc_html($custom_header) . "</div>";
?>

05Prevention Checklist

Treat all HTTP headers as untrusted input.
Apply the same validation and sanitization rules to headers as you would to query parameters or POST data.
Encode output based on context.
Use context-appropriate encoding (HTML entity encoding for HTML, JavaScript escaping for JavaScript, URL encoding for URLs) when embedding header values in responses.
Use templating engines safely.
If using a template engine, ensure it auto-escapes by default, or explicitly mark header values as needing escaping.
Validate header format and length.
Reject headers that don't match expected patterns (e.g., a custom header should only contain alphanumeric characters if that's all you expect).
Avoid passing headers to code interpreters.
Never pass raw header values to eval(), template engines in unsafe mode, or other dynamic code execution contexts.
Use security headers.
Implement Content-Security-Policy to restrict script execution and reduce the impact of injected scripts.

06Signs You May Already Be Affected

Check your application logs for unusual or suspicious values in HTTP headers (especially custom headers or User-Agent). Look for patterns like <script>, javascript:, event handler attributes (onerror=, onload=), or HTML tags in header values. If you see these reflected in your application's output or error pages, the application may be vulnerable.

07Related Recent Vulnerabilities