feat(proxy): harden the egress proxy sidecar + bound concurrent connections (HF Issue 2) - #88
Merged
Merged
Conversation
…ctions (HF Issue 2) The proxy is the dual-homed bridge whose compromise reproduces the HF incident, so it must be hardened at least as much as the agent it protects. It previously got only --read-only --cap-drop ALL; the agent gets far more. Run flags (sandy): add --security-opt no-new-privileges:true, --pids-limit 128, --memory 256m to proxy_run. Not --user: the binary binds :53/:80/:443, so a non-root uid would need CAP_NET_BIND_SERVICE or the unprivileged-port sysctl, reopening a cap on a cap-dropped read-only scratch image for marginal gain (evaluated, declined — documented). Connection bound (proxy/accept.go): the three identical accept loops (transparent/connect/forward) now share acceptLoop, which acquires a slot from a maxConns(512) semaphore BEFORE Accept — so a connection storm applies backpressure at the kernel backlog instead of growing goroutines/memory without bound. The --memory cap is then a backstop, not the enforcer (the finding's 'substantive half'). proxy/accept_test.go asserts the bound; full proxy suite passes -race. - run-tests.sh §50: assert the three new proxy_run flags. - CLAUDE.md + SPEC: document the hardening + semaphore. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sue 2) The Issue 2 refactor centralized the per-connection 'go guard(...)' spawn into acceptLoop (proxy/accept.go); the three listeners now dispatch via acceptLoop instead of each spawning their own guarded goroutine. The invariant is unchanged (every per-connection goroutine is still guarded), so §53 now asserts accept.go carries the guarded spawn and each listener routes through acceptLoop. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
HF-incident analysis Issue 2 (Low–Medium; defence-in-depth on the incident's exact target).
The egress proxy is the dual-homed container that bridges the
--internalsidecar to the internet — the component whose compromise is the incident. It was hardened less than the agent it protects (only--read-only --cap-drop ALL).Run flags (
sandy): add--security-opt no-new-privileges:true,--pids-limit 128,--memory 256mtoproxy_run.--userevaluated and declined (documented): the binary binds privileged ports :53/:80/:443, so a non-root uid needsCAP_NET_BIND_SERVICEre-added or the unprivileged-port sysctl — reopening a capability on a cap-dropped, read-only, single-static-binary scratch image for marginal gain.Connection bound (
proxy/accept.go): the three identical accept loops (transparent/CONNECT/forward) now shareacceptLoop, which acquires amaxConns(512)semaphore slot beforeAccept— so a connection storm (self-inflicted or injected) applies backpressure at the kernel backlog instead of growing goroutines/memory without bound. The--memorycap becomes a backstop, not the enforcer (the finding's 'substantive half').proxy/accept_test.goasserts the bound; the full proxy suite passes-race.run-tests.sh §50: assert the three new proxy_run flags.