Cloudanix VulnDB

CVE-2026-3902

High · 7.5

CVSS

7.5

EPSS

0.5%

Published

Apr 7, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A flaw in some Django web applications can let outsiders confuse the application about which request information to trust, potentially causing it to make the wrong access or routing decision.

Chainable
Exploitation
Remote Unauthenticated
Attacker needs
None
Complexity
Low
Impact
Data Tampering
Component
Web Framework
Class
Improper Input Validation
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

Django ASGIRequest incorrectly normalizes HTTP header names such that two distinct incoming header variants, one using hyphens and one using underscores, can collapse to the same underscore-based key. A remote unauthenticated attacker can exploit this ambiguity by sending crafted headers that cause application code, middleware, authentication layers, proxy-integration logic, or authorization checks to read an attacker-controlled header value instead of the value intended by the server or upstream infrastructure. The primary impact is integrity compromise: security decisions based on request headers can be spoofed or bypassed, depending on how the Django application uses headers.

Why it matters to the business

Applications that trust request headers for identity, authorization, routing, tenant selection, IP allowlisting, audit attribution, or feature access could make incorrect decisions, potentially allowing unauthorized access or manipulation of business workflows. The issue affects supported Django 6.0, 5.2, and 4.2 release lines before their fixed versions, and older unsupported series may also be affected, increasing risk for organizations running legacy Django deployments. Although this vulnerability is not currently listed in CISA KEV, has no known mature public exploitation in the provided data, and has a low EPSS score, it is remotely reachable and unauthenticated, so internet-facing ASGI Django applications should be prioritized for upgrade.

How an attack unfolds

An attacker first identifies a Django application served through ASGI and determines, by behavior or documentation, whether the application or its middleware trusts HTTP headers for security-sensitive decisions. The attacker then sends requests containing ambiguous versions of the same logical header, for example one form using hyphens and another using underscores. Because vulnerable Django versions map both variants into a single underscore-normalized representation, the attacker can influence which value the application reads. If the application relies on that header for authentication context, original client IP, forwarded host, role, organization, or routing decisions, the spoofed value may be accepted as authoritative. Successful exploitation does not require credentials or user interaction; the outcome depends on whether downstream application logic treats the affected header value as trusted input.

How to fix it

Upgrade Django to a fixed supported release: upgrade 6.0.x to 6.0.4 or later, 5.2.x to 5.2.13 or later, and 4.2.x to 4.2.30 or later. If running an unsupported Django series such as 5.0.x, 4.1.x, or 3.2.x, migrate to a supported fixed branch because those versions were not evaluated and may be affected. As a defense-in-depth mitigation, avoid making authorization or authentication decisions directly from client-supplied headers unless they are explicitly set and sanitized by a trusted reverse proxy. Configure front-end proxies and load balancers to reject or strip inbound headers containing underscores where possible, normalize duplicate security-sensitive headers, and ensure only trusted infrastructure can set headers such as forwarded identity, client IP, host, protocol, role, or tenant context.

How to confirm the fix worked

Confirm the installed Django version is 6.0.4 or later, 5.2.13 or later, or 4.2.30 or later on every deployed application artifact, container image, virtual environment, and build dependency lockfile. Review dependency manifests such as requirements.txt, pyproject.toml, poetry.lock, Pipfile.lock, and container SBOMs for vulnerable Django versions. Perform a safe test against staging or a controlled endpoint by sending two variants of the same header, one using hyphens and one using underscores, and verify that the application no longer allows ambiguous header spoofing or security-sensitive behavior changes. Validate proxy rules by confirming requests with underscore-containing headers are rejected, stripped, or consistently normalized before reaching Django. Review application code and middleware for use of request headers in authorization, identity, tenant selection, IP allowlisting, or audit decisions.

Typical attack path

  1. Identify a web application built on a vulnerable Django version and deployed with ASGI.
  2. Probe application behavior with duplicate or near-duplicate HTTP headers that differ only by hyphen versus underscore usage.
  3. Determine whether any security-sensitive behavior changes based on the ambiguous header value, such as access control, redirects, identity context, or IP-based restrictions.
  4. Send a crafted request containing both header variants so that Django exposes the attacker-chosen value to application code.
  5. Abuse the spoofed header interpretation to bypass or manipulate authorization, request attribution, routing, or other business logic.

How to detect it

To assess whether exploitation may have occurred, review HTTP access logs, reverse-proxy logs, WAF logs, CDN request logs, and application request logs for requests containing underscore-bearing headers or pairs of headers that differ only by hyphen versus underscore. Focus on endpoints that perform login, single sign-on callbacks, administrative actions, tenant or organization selection, API authorization, redirects, or IP-restricted functions. Look for suspicious combinations such as both X-Forwarded-For and X_Forwarded_For, X-Forwarded-Host and X_Forwarded_Host, X-Real-IP and X_Real_IP, Host-related forwarding headers, or custom identity/role headers sent by external clients. Correlate these requests with unexpected privilege changes, access from unusual source IPs, tenant-boundary violations, anomalous audit user attribution, unusual redirect behavior, or successful requests that should have failed authorization. If detailed raw header logging was not enabled, use WAF/CDN/proxy telemetry where raw request headers may still be available; standard application logs may not preserve the original ambiguous header names after Django normalization.

  • X_Forwarded_For
  • X-Forwarded-For
  • X_Forwarded_Host
  • X-Forwarded-Host
  • X_Forwarded_Proto
  • X-Forwarded-Proto
  • X_Real_IP
  • X-Real-IP
  • X_Original_URL
  • X-Original-URL
  • X_Rewrite_URL
  • X-Rewrite-URL
  • X_Remote_User
  • X-Remote-User
  • X_Forwarded_User
  • X-Forwarded-User
  • X_Forwarded_Email
  • X-Forwarded-Email
  • X_Forwarded_Role
  • X-Forwarded-Role
  • X_Forwarded_Groups
  • X-Forwarded-Groups
  • HTTP_X_FORWARDED_FOR
  • HTTP_X_FORWARDED_HOST
  • HTTP_X_FORWARDED_PROTO
  • HTTP_X_REAL_IP
  • HTTP_X_REMOTE_USER

What your security team should do

  • Inventory all Django applications, especially ASGI deployments, and identify versions earlier than 6.0.4, 5.2.13, or 4.2.30.
  • Prioritize upgrades for internet-facing applications and any service that trusts HTTP headers for authentication, authorization, client IP, tenant routing, or upstream identity.
  • Migrate unsupported Django branches to a supported fixed release rather than relying on unverified legacy behavior.
  • Add reverse-proxy controls to strip or reject client-supplied headers containing underscores and to canonicalize or block duplicate security-sensitive headers.
  • Search application code and middleware for security decisions based on request headers and replace implicit trust with explicit trusted-proxy validation.
  • Add logging for suspicious requests containing both hyphenated and underscore variants of the same header name.
  • Run regression tests for authentication, authorization, forwarded-header handling, and tenant-routing logic after the upgrade.
  • Monitor for exploit development despite the currently low EPSS score and absence from the CISA KEV catalog.

The record

An issue was discovered in 6.0 before 6.0.4, 5.2 before 5.2.13, and 4.2 before 4.2.30. `ASGIRequest` allows a remote attacker to spoof headers by exploiting an ambiguous mapping of two header variants (with hyphens or with underscores) to a single version with underscores. Earlier, unsupported Django series (such as 5.0.x, 4.1.x, and 3.2.x) were not evaluated and may also be affected. Django would like to thank Tarek Nakkouch for reporting this issue.

Affected packages

Ecosystem Package Introduced Fixed
openSUSE:Leap 16.0 python-Django 0 5.2.4-bp160.7.1
openSUSE:Tumbleweed python-Django 0 5.2.13-1.1
openSUSE:Tumbleweed python-Django4 0 4.2.30-1.1
openSUSE:Tumbleweed python-Django6 0 6.0.4-1.1

Related vulnerabilities