Gakido: When 'Performance First' Means 'Security Optional' (CVE-2026-24489)
Jan 26, 2026·4 min read·3 visits
Executive Summary (TL;DR)
Gakido, a 'performance-first' Python HTTP client, forgot that HTTP is a text protocol delimited by newlines. By injecting CRLF sequences (`\r\n`) into header values, attackers can break the protocol framing, leading to Request Smuggling or Header Injection. Patched in v0.1.1 by stripping control characters.
A classic CRLF injection vulnerability in the Gakido HTTP client allows attackers to inject arbitrary HTTP headers or manipulate request bodies via unsanitized input.
The Hook: Speed Kills (Safety)
In the world of Python HTTP clients, everyone wants to be faster than requests. Enter Gakido, a library explicitly marketing itself as a "performance-first" CPython HTTP client. Whenever I see "performance-first" in a README, my ears perk up. Usually, that translates to "we removed all the boring safety checks that were slowing us down."
True to form, Gakido managed to resurrect one of the oldest bugs in the web security handbook: CRLF Injection. It’s almost nostalgic. While modern libraries like httpx or aiohttp have spent years battle-hardening their parsers against protocol deviation, Gakido decided to trust user input implicitly.
The vulnerability is simple yet devastating: the library treated HTTP headers as simple strings to be concatenated, rather than structured data requiring strict serialization rules. This allowed users (and by extension, attackers) to rewrite the HTTP request envelope from the inside out.
The Flaw: Trusting the Carriage Return
HTTP/1.1 is, at its core, a text-based conversation. It relies on specific delimiters to understand where a header name ends, where a value begins, and where the headers stop and the body starts. The magic sequence is \r\n (Carriage Return + Line Feed).
The logic flaw in Gakido was located in gakido/headers.py, specifically within the canonicalize_headers function. This function's job is to merge default headers (like User-Agent) with user-supplied headers.
A robust client would validate that a header name or value does not contain control characters. Gakido, however, took the naive approach: it simply took the strings provided by the user and prepared them for the socket. If a user provided a value containing \r\n, the underlying socket writer would blindly transmit it, tricking the receiving server into thinking a new header (or a new request) had started.
The Code: The Smoking Gun
Let's look at the crime scene. Before the patch, the code simply iterated over headers and merged them. There were zero checks for forbidden characters.
The fix, applied in commit 369c67e67c63da510c8a9ab021e54a92ccf1f788, introduced a sanitizer. Here is the before-and-after logic:
The Vulnerable Logic (Conceptual)
# pseudo-code of the vulnerable state
for name, value in user_headers.items():
# No validation!
merged_headers[name] = valueThe Fix
The developer introduced a _sanitize_header helper that acts as a bouncer, stripping out the bad characters before they hit the club.
def _sanitize_header(name: str, value: str) -> tuple[str, str]:
"""
Sanitize header name and value to prevent HTTP header injection (CRLF injection).
Strips CR, LF, and null bytes from both name and value.
"""
# Look at this aggressive stripping strategy
clean_name = name.replace("\r", "").replace("\n", "").replace("\x00", "")
clean_value = value.replace("\r", "").replace("\n", "").replace("\x00", "")
return clean_name, clean_value> [!NOTE]
> Researcher Note: The fix uses a sanitize (strip) approach rather than a validate (reject) approach. This is risky. If I send Ad\rmin, Gakido changes it to Admin. This could potentially be abused to bypass string-matching filters in the application layer that look for "Admin" before the HTTP client is called.
The Exploit: Smuggling Headers
Exploiting this is trivial if you control any string that ends up in a header. Let's assume the application takes a query parameter client_id and uses it in a custom header X-Client-ID for backend tracking.
The Setup
Attacker sends input: guineapig\r\nCookie: session_id=admin_token
The Execution
The vulnerable code constructs the raw HTTP message:
GET /resource HTTP/1.1
Host: internal-api
X-Client-ID: guineapig
Cookie: session_id=admin_token
User-Agent: Gakido/0.1.0The Result
The backend server parses X-Client-ID as just guineapig. It then sees a newline and parses Cookie: session_id=admin_token as a completely valid, separate header.
We have successfully injected a session cookie, effectively hijacking the request context. If we inject two CRLFs (\r\n\r\n), we can terminate the headers entirely and start writing a fake request body or a second request (Request Smuggling), which is catastrophic in microservices environments.
The Fix & Limitations
The remediation is straightforward: Upgrade to Gakido v0.1.1. The patch sanitizes inputs by removing the offending bytes.
However, security teams should remain skeptical.
- The Native Bypass: Gakido uses C extensions for speed. If the C-level transport logic (
_gakido_native) bypasses the Python-levelcanonicalize_headersfunction, the vulnerability might still exist in the compiled binary. - Unicode weirdness: The patch strips standard ASCII control characters. It does not appear to handle Unicode line separators like
U+2028, which some eccentric backend parsers might treat as newlines.
For now, the bleeding has stopped, but you should treat this library like a loaded gun: handle with extreme care.
Official Patches
Fix Analysis (1)
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:NAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
Gakido HappyHackingSpace | < 0.1.1 | 0.1.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-113 |
| Attack Vector | Network |
| CVSS | 7.5 (High) |
| Impact | Request Smuggling / Header Injection |
| Affected Component | gakido/headers.py |
| Patch Commit | 369c67e67c63da510c8a9ab021e54a92ccf1f788 |
MITRE ATT&CK Mapping
Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting')
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.