Weakness reference
CWE-436

Interpretation Conflict

An interpretation conflict occurs when different components in a system parse or understand the same input in incompatible ways. A security control such as a…

01Summary

An interpretation conflict occurs when different components in a system parse or understand the same input in incompatible ways. A security control (such as a firewall, WAF, or input validator) may reject malicious input based on one interpretation, while the backend application processes the same input under a different interpretation, allowing an attack to slip through. This mismatch is a form of security bypass.

02How It Happens

Interpretation conflicts arise when two or more components in a request path apply different parsing rules, character encodings, or normalization logic to the same data. For example, a web application firewall might decode URL-encoded input once and check it against a blocklist, while the backend application decodes it twice—or interprets path separators differently. A validator might treat a null byte as a string terminator, while the backend ignores it. Character encoding mismatches (UTF-8 vs. UTF-16, or overlong UTF-8 sequences) can also cause the same byte sequence to be understood as different characters by different layers. When the validator and the target disagree, an attacker can craft input that passes the security check but executes differently in the application.

03Real-World Impact

Interpretation conflicts can lead to complete bypass of security controls. An attacker might inject SQL, cross-site scripting (XSS), path traversal, or command injection payloads that are rejected by a WAF but executed by the application. This can result in unauthorized data access, account compromise, remote code execution, or site defacement. The vulnerability is particularly dangerous because it often affects multiple applications or versions simultaneously if they share a common misunderstanding about how input should be parsed.

04Vulnerable & Fixed Patterns

Vulnerable pattern
# Validator (e.g., WAF or middleware)
def validate_input(user_input):
    decoded = user_input.replace('%2e', '.')  # Decode once
    if '..' in decoded or 'admin' in decoded:
        return False
    return True

# Backend application
def process_file(user_input):
    # Decodes again, or interprets differently
    decoded = user_input.replace('%2e', '.').replace('%252e', '%2e')
    file_path = f'/var/www/{decoded}'
    with open(file_path, 'r') as f:
        return f.read()

# Attacker sends: "..%252fadmin%252fconfig.txt"
# Validator sees: "..%2fadmin%2fconfig.txt" (no ".." or "admin" after first decode)
# Backend sees: "../admin/config.txt" (after second decode)

Why it's vulnerable:
The validator and backend apply different decoding logic, allowing an attacker to craft input that bypasses the check but is interpreted as malicious by the application.

Fixed pattern
# Normalize input once, early, in a shared utility
def normalize_input(user_input):
    # Decode fully and consistently
    decoded = user_input
    while '%' in decoded:
        decoded = urllib.parse.unquote(decoded)
    # Reject suspicious patterns after normalization
    if '..' in decoded or 'admin' in decoded:
        raise ValueError("Invalid input")
    return decoded

# Both validator and backend use the same function
def validate_input(user_input):
    try:
        normalize_input(user_input)
        return True
    except ValueError:
        return False

def process_file(user_input):
    decoded = normalize_input(user_input)
    file_path = f'/var/www/{decoded}'
    with open(file_path, 'r') as f:
        return f.read()
Vulnerable pattern
// Validator (e.g., WAF or input filter)
function validate_input($user_input) {
    $decoded = str_replace('%2e', '.', $user_input);
    if (strpos($decoded, '..') !== false || strpos($decoded, 'admin') !== false) {
        return false;
    }
    return true;
}

// Backend application
function process_file($user_input) {
    // Decodes differently or multiple times
    $decoded = urldecode($user_input);
    $file_path = '/var/www/' . $decoded;
    return file_get_contents($file_path);
}

// Attacker sends: "..%252fadmin%252fconfig.txt"
// Validator sees: "..%2fadmin%2fconfig.txt" (safe)
// Backend sees: "../admin/config.txt" (unsafe)

Why it's vulnerable:
The validator uses manual string replacement while the backend uses urldecode(), causing them to interpret the same input differently.

Fixed pattern
// Centralized normalization function
function normalize_input($user_input) {
    // Decode fully and consistently
    $decoded = $user_input;
    while (strpos($decoded, '%') !== false) {
        $re_decoded = urldecode($decoded);
        if ($re_decoded === $decoded) break; // Stop if no change
        $decoded = $re_decoded;
    }
    // Reject suspicious patterns after normalization
    if (strpos($decoded, '..') !== false || strpos($decoded, 'admin') !== false) {
        throw new Exception("Invalid input");
    }
    return $decoded;
}

// Both validator and backend use the same function
function validate_input($user_input) {
    try {
        normalize_input($user_input);
        return true;
    } catch (Exception $e) {
        return false;
    }
}

function process_file($user_input) {
    $decoded = normalize_input($user_input);
    $file_path = '/var/www/' . $decoded;
    return file_get_contents($file_path);
}

05Prevention Checklist

Normalize input once, early, and consistently.
Define a single, shared normalization function (decoding, case conversion, whitespace handling) that all components use before validation or processing.
Validate after normalization, not before.
Apply security checks to the fully decoded/normalized form, not to raw input.
Document parsing assumptions.
Ensure all components (WAF, middleware, application, database driver) agree on character encoding, path separator interpretation, and null-byte handling.
Test with encoded and edge-case inputs.
Include double-encoded, mixed-case, and alternative-encoding variants in your test suite to catch interpretation mismatches.
Use allowlists, not blocklists.
Define what *is* acceptable (e.g., alphanumeric + specific safe characters) rather than trying to block all bad patterns.
Keep security components in sync.
If you update your WAF rules, ensure the backend validation logic is updated to match, and vice versa.

06Signs You May Already Be Affected

Look for access logs showing requests that were rejected by your WAF or input filter but succeeded in the application, or unusual file access patterns (e.g., reads from unexpected directories). Check for multiple versions of the same security rule across different components, which may indicate inconsistent interpretation. Review error logs for decoding or parsing warnings that suggest input is being processed differently at different layers.

07Related Recent Vulnerabilities