Safeguard
Application Security•

CWE-81 XSS in Error Message Pages: How to Fix It

Custom 403 and 404 pages that echo the request are a classic XSS spot. CWE-81 explains why, and the simplest fix is to stop echoing input.

Safeguard Security Team
2 min read

CWE-81 covers a product that receives input from an upstream component but does not neutralize special characters that could be read as web-scripting elements when they are sent to an error page.

Error pages are easy to forget. Every web server and framework has them, and many show the URL or message that caused the error.

How it happens

Error pages include customized 403 Forbidden or 404 Not Found pages. When an attacker can trigger an error whose message contains script syntax from the attacker's input, cross-site scripting becomes possible. The attacker only needs a victim to open a crafted link that produces the error.

A small Python example:

@app.errorhandler(404)
def not_found(e):
    # Vulnerable: echoes the requested path unescaped
    return "<p>No page at " + request.path + "</p>", 404

# Safer: do not echo input, or escape it
@app.errorhandler(404)
def not_found(e):
    return "<p>Page not found.</p>", 404

The observed examples include CVE-2002-0840 (XSS in the default error page from the Host header), CVE-2002-1053 (XSS in an error message) and CVE-2002-1700 (XSS in an error page from a targeted parameter). See CVE-2002-0840, CVE-2002-1053 and CVE-2002-1700. Note that one of them came from a header, not a form field.

A related, more recent record is in the CWE-79 list: CVE-2021-25963 describes a Python-based e-commerce platform that did not escape returned content on error pages.

What an attacker gains

MITRE lists confidentiality, integrity and availability, through reading application data and executing unauthorized code or commands in the victim's browser.

How to find it

MITRE lists automated static analysis (SAST), which models data flow in source or compiled code. Add manual testing: request nonexistent pages, send bad headers and break parameters on purpose, and read each error page for echoed input.

How to fix it

  1. Do not write user-controlled input to error pages. This is MITRE's first mitigation and the simplest.
  2. If you must show it, check against an allowlist and neutralize all request data, including headers, cookies, hidden fields and the URL.
  3. Encode on output for the page context.

Quick check

What is the simplest way to avoid CWE-81?

Do not put user-controlled input on error pages at all.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.