Granian CVE-2026-42545
MEDIUMSeverity by source
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
Lifecycle Timeline
3DescriptionGitHub Advisory
Summary
Granian aborts a worker process if a WSGI application returns an invalid HTTP response header name or value. The WSGI response conversion path uses .unwrap() on both the header name and header value constructors, so malformed output from the application becomes a process abort instead of a handled error.
This issue requires a buggy or attacker-influenced WSGI application to emit invalid headers. It is not a parser bug in Granian's request path. The security impact is that application mistakes which should result in a 500 instead kill the worker process.
Details
https://github.com/emmett-framework/granian/blob/bdd5b0fbbb2aca6f2f4c0d2700c244d190958035/src/wsgi/io.rs#L39-L42
If either conversion fails, .unwrap() panics. In release builds Granian uses panic = "abort", so the panic terminates the worker.
Preconditions
The attacker must be able to influence a header name or value produced by the WSGI application, or the application must otherwise generate invalid headers.
Examples include:
- a header name containing a space
- a header value containing
\r\n - a header value containing a null byte
These are realistic failure modes for applications that reflect user-controlled data into headers such as Location, Content Disposition, or custom response headers.
PoC
Step 1
start Granian with the PoC WSGI app
# app.py
def app(environ, start_response):
path = environ.get("PATH_INFO", "/")
if path == "/crash-name":
headers = [("X Bad Name", "value")]
elif path == "/crash-value":
headers = [("Content-Type", "text/html\r\nX-Injected: evil")]
elif path == "/crash-null":
headers = [("X-Custom", "value\x00end")]
else:
start_response("200 OK", [("Content-Type", "text/plain")])
return [b"OK - server alive\n"]
start_response("200 OK", headers)
return [b"This response kills the worker\n"]
granian --interface wsgi app:app --host 127.0.0.1 --port 8000Step 2
trigger the crash (any one of these is sufficient)
curl http://127.0.0.1:8000/crash-name
curl http://127.0.0.1:8000/crash-value
curl http://127.0.0.1:8000/crash-nullExpected result:
- the worker aborts after any of the crash paths
- subsequent requests fail until the worker is restarted
Impact
- Worker process denial of service
- A single bad response kills one worker
- Application bugs become process crashes instead of request-scoped failures
AnalysisAI
Granian worker process aborts when a WSGI application returns invalid HTTP response header names or values due to unhandled panic in the header conversion path. An attacker who can influence WSGI application output, such as by injecting user-controlled data into response headers like Location or Content-Disposition, can trigger worker process denial of service. The vulnerability affects Granian versions 0.2.0 through 2.7.3; patch available in version 2.7.4. Proof of concept demonstrates crashes via headers containing spaces, CRLF injection, or null bytes.
Technical ContextAI
Granian is a Rust-based ASGI/WSGI application server. The vulnerability exists in the WSGI response handling code at src/wsgi/io.rs lines 39-42, where the header name and value constructors use Rust's .unwrap() method without error handling. When a WSGI application produces invalid HTTP headers-such as header names with spaces, header values containing carriage return/line feed (CRLF) sequences, or null bytes-the constructors fail validation. In Rust, unwrap() on a failed Result panics; Granian is compiled with panic = "abort" in release builds, causing the entire worker process to terminate instead of gracefully returning a 500 error. This is fundamentally a CWE-248 (Uncaught Exception) issue where error conditions that should be handled at the application layer instead propagate as fatal process crashes. The root cause is not a parser vulnerability in Granian's request path but rather insufficient input validation in the response serialization path.
RemediationAI
Upgrade Granian to version 2.7.4 or later, which resolves the .unwrap() panic by implementing proper error handling for invalid header names and values. The patch replaces unwrap() calls with error propagation that returns a 500 Internal Server Error to the client instead of aborting the worker process. For organizations unable to immediately upgrade, the primary mitigation is to sanitize all user-controlled data before it is reflected into response headers in the WSGI application layer. Specifically, validate that header names contain only alphanumeric characters and hyphens (per RFC 7230), header values do not contain CRLF or null bytes, and consider using a header validation library in your framework (e.g., Werkzeug's Headers class for Flask applications). This mitigation does not eliminate the root cause in Granian but reduces the attack surface by preventing the malformed headers from being generated. Load-balanced deployments should monitor worker restarts and alert on excessive crashes, which may indicate application bugs or attack attempts. The advisory is available at https://github.com/advisories/GHSA-f5p7-9fr5-8jmj.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing
Same weakness CWE-248 – Uncaught Exception
View allSame technique Denial Of Service
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-f5p7-9fr5-8jmj