# Squidbleed (CVE-2026-47729)

Squid's FTP directory listing parser overreads heap memory via strchr('\0') quirk, leaking other users' cleartext HTTP requests including Authorization headers.

- Payout: Research
- Severity: medium
- Program: Squid Proxy
- Write-up by: Calif
- Disclosed: 2026-06-18
- CVE: CVE-2026-47729
- Write-up quality: 8/10
- Original: https://blog.calif.io/p/squidbleed-cve-2026-47729
- Library page: https://bugbountylibrary.com/r/blog%3Ablog-calif-io-p-squidbleed-cve-2026-47729
- Tags: area:cloud domain:infra impact:data-leak impact:internal-access kind:research platform:research sev:medium tech:linux technique:legacy-endpoint technique:source-review vuln:info-disclosure vuln:memory-corruption

**Target:** Squid FTP directory listing parser (htmlifyListEntry)
**Root cause:** In the NetWare skip_whitespace path, `while (strchr(w_space, *copyFrom))` treats the terminating NUL as whitespace since strchr matches '\0', so copyFrom advances past the buffer end when a listing line has no filename.
**Steps:**
1. Attacker controls an FTP server reachable from the proxy on port 21 (default Safe_ports ACL).
2. Victim sends a cleartext HTTP request (or >2KB request promoted to MEM_4K_BUF) through the same Squid proxy; buffer is freed to MEM_4K_BUF freelist.
3. Attacker requests an FTP directory listing from their server whose banner contains 'NetWare' and returns a line with no filename: `d [R----F--] supervisor 512 Jan 16 18:53`.
4. Squid allocates the 4KB line buffer from MEM_4K_BUF, reclaiming the victim's stale buffer; parser overreads past NUL and xstrdup copies leaked bytes as the filename.
5. Leaked memory is returned in the generated HTML directory listing.
**How found:** Prompted an LLM to investigate the full FTP state machine; it flagged that strchr(w_space, '\0') returns non-NULL per C11 §7.24.5.2, making the whitespace-skip loop walk past the terminator when no filename follows the timestamp.
**Exploitation:** Attacker needs a reachable FTP server and shared proxy with victim. Spray FTP listing requests to reclaim freed MEM_4K_BUF buffers previously holding victim HTTP requests; the overread filename field returns stale request bytes including Authorization headers.
**Insight:** strchr/strcspn-style scans treat the terminating NUL as a member of the string; any loop advancing a pointer while strchr(set, *p) is truthy will run off the end on empty trailing fields. Audit legacy compat paths (NetWare/whitespace-skip branches) where such loops survive.

## Proof of concept (copied exactly from the original report)

**Malicious FTP listing line with no filename**

```
d [R----F--] supervisor 512 Jan 16 18:53
```

**Vulnerable strchr whitespace-skip loop**

```
copyFrom = buf + tokens[i + 2].pos + strlen(tokens[i + 2].token);
if (flags.skip_whitespace) {
 while (strchr(w_space, *copyFrom))
 ++copyFrom;
} else {
 /* Handle the following four formats:
 * "MMM DD YYYY Name"
 * "MMM DD YYYYName"
 * "MMM DD YYYY Name"
 * "MMM DD YYYY Name"
 * Assuming a single space between date and filename
 * suggested by: Nathan.Bailey@cc.monash.edu.au and
 * Mike Battersby <mike@starbug.bofh.asn.au> */
 if (strchr(w_space, *copyFrom))
 ++copyFrom;
}
p->name = xstrdup(copyFrom);
```

