Feb 10, 2026·6 min read·25 visits
Emmett < 1.3.11 crashes when parsing malformed cookies. An attacker can send a request with a cookie key containing characters like '(' or '[' to trigger an unhandled `CookieError`, resulting in a 500 Internal Server Error. Trivial to exploit for DoS.
A classic input validation oversight in the Emmett Python web framework allows unauthenticated attackers to trigger unhandled exceptions by sending malformed HTTP Cookie headers. By leveraging the strict parsing logic of Python's standard library `http.cookies`, an attacker can force the application to crash (HTTP 500) on every request containing specific illegal characters. While not a Remote Code Execution (RCE) vector, this vulnerability presents a trivial, low-cost method for Denial of Service (DoS) attacks against any application running affected versions of Emmett.
In the world of Python web frameworks, performance is often a game of "don't compute it until you need it." Emmett, a framework known for its simplicity and speed, follows this philosophy. One of the things it evaluates lazily is the request.cookies property. The framework assumes that until your application logic actually asks for a cookie, there's no need to spend CPU cycles parsing that messy Cookie header string coming from the browser.
But here is the catch: lazy evaluation is a double-edged sword. If the mechanism that parses that data is fragile, and the parsing happens implicitly deep within the framework's request lifecycle, a crash there doesn't just return None or an empty dictionary. It propagates an unhandled exception all the way up the stack.
CVE-2026-25577 is exactly this scenario. It is a reminder that the boundary between your application and the wild, untrusted internet is often thinner than you think. It relies on the interaction between Emmett's wrapper logic and Python's notoriously strict standard library http.cookies. The result? You can take down a request thread with a single character.
The root cause of this vulnerability lies in a mismatch of expectations. Emmett delegates the heavy lifting of cookie parsing to Python's built-in http.cookies.SimpleCookie. Now, if you have ever worked with Python's SimpleCookie, you know it is somewhat of a pedant. It adheres strictly to older cookie specifications.
If you feed SimpleCookie.load() a string that contains characters it deems "illegal" in a key (such as spaces, square brackets [], or parentheses ()), it does not just ignore the bad segment. It screams. It raises a CookieError.
In a robust web server, you expect the framework to act as a blast shield. It should catch the shrapnel coming from the network, filter it, and hand you clean objects. Emmett, in versions prior to 1.3.11, failed to put up that shield. It took the raw Cookie header, split it by semicolons, and fed each chunk directly into the maw of SimpleCookie.load(). Because there was no try...except block wrapping this operation, a single malformed cookie sent by a malicious client would cause the parser to throw an exception that the framework wasn't expecting, leading directly to an HTTP 500 Internal Server Error.
Let's look at the smoking gun in emmett_core/http/wrappers/__init__.py. This is where the framework tries to convert the raw header string into a nice dictionary-like object.
The Vulnerable Code:
# emmett_core/http/wrappers/__init__.py
def cookies(self) -> SimpleCookie:
cookies: SimpleCookie = SimpleCookie()
# Split the header by semicolon and process blindly
for cookie in self.headers.get("cookie", "").split(";"):
cookies.load(cookie) # <--- The Kill Switch
return cookiesIt looks innocent, right? Standard Python. But cookies.load(cookie) is a ticking time bomb if cookie is something like session_id(=123. The ( character is illegal in a cookie key.
The Fix (Commit c126757133e118119a280b58f3bb345b1c9a8a2a):
The maintainers patched this by wrapping the load operation in a try...except block. This is the definition of defensive programming.
# emmett_core/http/wrappers/__init__.py
def cookies(self) -> SimpleCookie:
cookies: SimpleCookie = SimpleCookie()
for cookie in self.headers.get("cookie", "").split(";"):
try:
cookies.load(cookie)
except Exception:
continue # Just skip the bad crumb
return cookiesNow, if a user sends garbage, Emmett simply shrugs, discards the malformed segment, and continues parsing the rest. The application stays alive.
Exploiting this is trivially easy. You don't need shellcode, you don't need memory addresses, and you don't need authentication. You just need curl.
The attack vector relies on sending a header that passes the web server (like Nginx) but fails in the application logic. Most reverse proxies are surprisingly lenient about what characters sit in a Cookie header, passing them through to the backend app.
Here is the attack flow:
Proof of Concept:
curl -v \
-H "Cookie: session=deadbeef; crash_me(=now" \
http://target.emmett-app.local/When the server receives this, the ( in crash_me(=now triggers the exception. The unhandled error propagates, the request handler dies, and the server returns a 500 error. If you put this in a loop, you can flood the server's logs and potentially exhaust worker threads if the error handling is resource-intensive.
It is easy to dismiss this as "just a 500 error." But in a security context, availability is critical. A single attacker with a basic script can effectively take a service offline for all legitimate users.
Consider the implications:
This is a low-skill, high-yield attack for anyone looking to cause disruption.
The remediation is straightforward. If you are using emmett-framework/core, you need to upgrade immediately.
Primary Mitigation:
pip install --upgrade emmett-coreDefense in Depth (WAF):
If you cannot upgrade immediately (perhaps you are stuck in dependency hell), you can mitigate this at the network edge. Configure your WAF or Load Balancer to drop requests containing non-RFC compliant characters in the Cookie header.
For example, an Nginx rule or a Cloudflare WAF rule regex matching Cookie headers with ( or [ can block the attack before it hits the Python code. However, relying on edge filtering is always riskier than patching the code itself.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
emmett-core emmett-framework | < 1.3.11 | 1.3.11 |
| Attribute | Detail |
|---|---|
| CWE | CWE-248 (Uncaught Exception) |
| CVSS v3.1 | 7.5 (High) |
| Attack Vector | Network (Remote) |
| Impact | Denial of Service (DoS) |
| Exploit Complexity | Low (Trivial) |
| Status | Patched |
The software does not correctly catch or handle exceptions, leading to a denial of service or unexpected state.
Januscape (CVE-2026-53359) is a critical Use-After-Free vulnerability in the x86 Shadow MMU component of the Linux Kernel's KVM subsystem. A logic error in shadow page tracking permits unauthorized page reuse without validating architectural execution roles, leading to dangling pointers in reverse mapping (rmap) tracking entries during guest memory teardown.
CVE-2026-48282 is a critical unauthenticated path traversal and arbitrary file write vulnerability in the Remote Development Services (RDS) component of Adobe ColdFusion. The vulnerability allows a remote, unauthenticated attacker to bypass directory boundaries and write arbitrary files, including CFML-based web shells, onto the host server. This flaw is actively exploited in the wild and enables full unauthenticated remote code execution under the privileges of the ColdFusion service account.
An information disclosure vulnerability exists in the web-auth/webauthn-lib PHP library when using the default SimpleFakeCredentialGenerator without a configured secret. This allows unauthenticated remote attackers to determine if a username exists on the target application.
A Stored and Reflected Cross-Site Scripting (XSS) vulnerability was identified in the Rust web service library 'rama' prior to version 0.3.0-rc.1. When serving directories using DirectoryServeMode::HtmlFileList, the library improperly escapes directory names, filenames, and request path components before injecting them into dynamically generated HTML files. This allows attackers to execute malicious scripts inside user browser sessions.
The ha-mcp add-on for Home Assistant exposes its settings and security policy routes without authentication at the bare root path of TCP port 9583. This exposure allows unauthorized adjacent network clients to reconfigure tools, alter policies, and bypass human-in-the-loop approval gates. The vulnerability has been addressed in development build 7.6.0.dev393 and subsequent releases by restricting access to root-mounted routes exclusively to the Supervisor Ingress IP.
An authentication freshness bypass vulnerability exists in the WebAuthn re-authentication path of Flask-Security-Too versions 5.8.0 and 5.8.1. The flaw allows an authenticated attacker to elevate the freshness status of a victim session using their own WebAuthn credential, bypassing re-authentication constraints.