Raw CONNECT tunnels bypass the Eval contamination filter and the egress audit log
#2,977 opened on Aug 13, 2026
Repository metrics
- Stars
- (1 star)
- PR merge metrics
- (PR metrics pending)
Description
packages/eval/harbor/egress_filter.py implements only the request hook and classifies flow.request.pretty_url. mitmproxy does not fire request for a CONNECT, and when the bytes inside an established tunnel are neither TLS nor HTTP, next_layer falls back to a raw TCP layer, so no hook runs at all. The flow reaches no contamination rule, and because hits.jsonl records only blocks and policy errors, it leaves no audit record either.
The namespace contract still holds — the traffic does go through mitmproxy. What does not hold is "audited", and with it the contamination blocklist the cohort leans on.
Reproduction
Against maka-eval-egress-proxy:12.2.3 built from packages/eval/harbor/egress-proxy/Dockerfile, from a subject under the proxy-only policy:
HTTP http://tbench.ai/x -> 451 tbench_domain filter works for plain HTTP
HTTP http://example.com/ -> 200
CONNECT ssh.github.com:443 -> HTTP/1.1 200 Connection established
first bytes from peer: SSH-2.0-... KEXINIT
CONNECT tbench.ai:443 -> HTTP/1.1 200 Connection established
GitHub's real SSH banner and key exchange came back, so git clone git@github.com:... through ssh.github.com:443 traverses the proxy without ever being classified. Note the second line too: tbench.ai is on the blocklist, and the CONNECT to it is answered 200. For a TLS client the inner request is still blocked after interception, so the exposure is raw tunnels.
Deliberate to exploit, not something a subject hits by accident.
Candidate directions
- Apply the host rules at
http_connect, so a blocklisted host is refused before the tunnel opens rather than after interception. Closes the blocklisted-host case, not the arbitrary-host one. - Hook
tcp_startand kill flows that fall back to raw TCP, with an audit record. Fail-closed, and nothing in a coding benchmark legitimately needs a non-HTTP tunnel through this proxy — SSH egress is already impossible except through it. - Record every tunnel, not only blocks. Changes what
hits.jsonlmeans and interacts with its 1 MiB cap.
Scope
Found while adjudicating the reviews of #2960, which states the gap in the README rather than closing it. This is the contamination blocklist's completeness, a separate concern from the namespace isolation that PR is about, and it needs mitmproxy hook work with its own tests.