Summary
The plain-HTTP relay path (handleHTTP in proxy/proxy.go) does not evaluate http-scope Keep policy at all — not even path rules. Only network policy is checked there. All http-scope Keep enforcement (path rules, and now request-body rules) lives in the HTTPS CONNECT/TLS-interception handler.
This means a client can bypass any http-scope policy — including the new request-body filtering — simply by routing a request over http:// instead of https://.
Where
proxy/proxy.go — handleHTTP (the non-CONNECT relay): runs checkNetworkPolicyForRequest but has no rc.KeepEngines["http"] evaluation before httpTransport.RoundTrip.
- Compare with the CONNECT interception handler, where the http-scope check (
buildHTTPCall + SafeEvaluate, fail-closed deny path) runs.
Impact
- Bypass vector: for any host reachable over plain HTTP, both path-based and body-based http-scope rules are silently skipped.
- Pre-existing gap (path rules were never enforced on this path); the new request-body filtering inherits the same gap.
Proposed fix
Wire the same http-scope evaluation into handleHTTP, before RoundTrip:
- Reuse
buildHTTPCall(eng, r, host) to buffer/parse the body when eng.RequiresBody("http"), restoring r.Body for the upstream request.
- Apply the same fail-closed deny path (malformed/oversized/non-JSON body → deny; eval error → deny;
Decision == Deny → deny).
- Mind the differing log/response shape in
handleHTTP (it uses a different RequestLogData/response-writing flow than the CONNECT handler).
Note / behavior change to weigh
Adding this introduces policy evaluation where there is none today, so it can deny plain-HTTP requests that previously passed. That's the intended security posture, but it should be called out in the changelog when shipped.
Context
Surfaced while adding http-scope request-body filtering (keep v0.5.0 NewHTTPCallWithBody / Engine.RequiresBody). That change was deliberately scoped to the HTTPS interception path; this issue tracks closing the plain-HTTP gap.
Summary
The plain-HTTP relay path (
handleHTTPinproxy/proxy.go) does not evaluate http-scope Keep policy at all — not even path rules. Only network policy is checked there. All http-scope Keep enforcement (path rules, and now request-body rules) lives in the HTTPS CONNECT/TLS-interception handler.This means a client can bypass any http-scope policy — including the new request-body filtering — simply by routing a request over
http://instead ofhttps://.Where
proxy/proxy.go—handleHTTP(the non-CONNECT relay): runscheckNetworkPolicyForRequestbut has norc.KeepEngines["http"]evaluation beforehttpTransport.RoundTrip.buildHTTPCall+SafeEvaluate, fail-closed deny path) runs.Impact
Proposed fix
Wire the same http-scope evaluation into
handleHTTP, beforeRoundTrip:buildHTTPCall(eng, r, host)to buffer/parse the body wheneng.RequiresBody("http"), restoringr.Bodyfor the upstream request.Decision == Deny→ deny).handleHTTP(it uses a differentRequestLogData/response-writing flow than the CONNECT handler).Note / behavior change to weigh
Adding this introduces policy evaluation where there is none today, so it can deny plain-HTTP requests that previously passed. That's the intended security posture, but it should be called out in the changelog when shipped.
Context
Surfaced while adding http-scope request-body filtering (keep v0.5.0
NewHTTPCallWithBody/Engine.RequiresBody). That change was deliberately scoped to the HTTPS interception path; this issue tracks closing the plain-HTTP gap.