CWE-838 is a product that uses or specifies an encoding when sending output to a downstream component, but the encoding does not match what that component expects. MITRE marks it as not language specific. Web pages, databases, shells, logs and APIs are all downstream components.
How it happens
The downstream component decodes using its own method and may produce different data than was intended. Even closely related encodings differ. If the boundary between control and data breaks, the result can contain control characters or special elements the sender never meant to send. That can bypass input validation and enable injection attacks.
MITRE's example is CVE-2009-2814: a server did not properly handle requests lacking UTF-8 data while the browser assumed UTF-8, allowing cross-site scripting.
# Vulnerable: no charset declared, browser guesses
return Response(page_html) # content type without charset
# Fixed: declare the encoding explicitly
return Response(page_html, content_type="text/html; charset=utf-8")
What an attacker gains
MITRE says an attacker could modify the structure of the message or data sent downstream, possibly injecting commands. It lists impact on integrity, confidentiality and availability, including modifying application data and executing unauthorized code or commands.
How to find it
MITRE lists automated static analysis, which can find some instances. In review, look at every place output leaves your code: HTML, JSON, SQL, shell, headers. Check that the encoding is declared and matches the receiver. Test with unusual character sets and multibyte input.
How to fix it
From MITRE:
- Use context aware encoding. Know which encoding the downstream component uses and apply it. Where an encoding can be specified, specify it instead of assuming defaults match.
- Prefer protocols and formats with strict boundaries between control and data. If not feasible, make sure they let both sides state which encoding is used.
- Use a vetted library or framework, such as an encoding control or a template system with built-in escaping.
For example, parameterized queries keep data separate from SQL, and template engines with automatic escaping handle HTML contexts.
Quick check
Why does a missing charset matter?
The browser may guess. If it guesses differently than your server assumed, characters can be decoded into markup you never intended.
Is one global escape function enough?
No. Escaping depends on context. HTML text, attributes, URLs and SQL need different handling.