fix(cred_proxy): close git-push bypass + route through pipelock (PRD 0010)
Three coupled fixes that close a documented bypass of git-gate's gitleaks pre-receive hook: 1. cred-proxy refuses git smart-HTTP push at runtime. Any path ending in /git-receive-pack or /info/refs?service=git-receive-pack returns 403 with a pointer at the bottle.git SSH path. Fetch (upload-pack) is still allowed — the bypass we're closing is push, where gitleaks is the load-bearing scanner. Hard guarantee. 2. The provisioner suppresses the cred-proxy `~/.gitconfig` insteadOf rewrite for any host already declared in bottle.git. git-gate is the canonical git path there; we don't write a competing rule that would let `git clone https://<host>/...` succeed in ways that confuse on push. Defense in depth — (1) is the hard guarantee. 3. cred-proxy routes its outbound HTTPS through pipelock. The sidecar's environ now sets HTTPS_PROXY=<pipelock-url>, and the image's entrypoint runs `update-ca-certificates` over the per-bottle pipelock CA (docker cp'd into /usr/local/share/ca-certificates/pipelock.crt before start) so the proxy's HTTPS client trusts pipelock's bumped certs. Consequence: pipelock's allowlist + body scanner now sit in the cred-proxy egress path the same way they sit in front of direct agent traffic. The cred-proxy upstream hosts (api.github.com, github.com, gitea hosts, registry.npmjs.org) come OFF pipelock's passthrough_domains. Only api.anthropic.com remains on passthrough (LLM body content legitimately trips DLP). PRD 0010 updated to reflect all three. Tests adjusted: the "cred-proxy hosts go on passthrough" assertion in test_pipelock_allowlist flips to "they don't", a new TestIsGitPushRequest exercises the smart-HTTP refusal predicate, and the gitconfig renderer tests cover the per-host suppression matrix.
This commit is contained in:
@@ -130,7 +130,16 @@ supported kinds (anthropic, github, gitea, npm):
|
||||
the agent's environ
|
||||
- `~/.npmrc` `registry = http://cred-proxy:<PORT>/npm/`
|
||||
- `~/.gitconfig` `[url …] insteadOf = …` for each declared
|
||||
`github` / `gitea` upstream
|
||||
`github` / `gitea` upstream, **except** when a `bottle.git`
|
||||
entry already brokers the same host. git-gate is the canonical
|
||||
git path on those hosts — its pre-receive runs gitleaks before
|
||||
forwarding the push; a cred-proxy `https://<host>/` rewrite
|
||||
would route HTTPS git ops around the gate, and `git push` over
|
||||
HTTPS to the same host via cred-proxy carries no gitleaks
|
||||
equivalent. (cred-proxy independently refuses smart-HTTP push
|
||||
paths at runtime — see "Smart-HTTP push refused" below — but
|
||||
suppressing the rewrite means `git clone https://<host>/...`
|
||||
doesn't have a tempting shortcut that just confuses later.)
|
||||
- `~/.config/tea/config.yml` with the proxy URL for each
|
||||
declared `gitea` entry
|
||||
- **Sidecar lifecycle.** Mirrors `DockerGitGate` /
|
||||
@@ -141,11 +150,27 @@ supported kinds (anthropic, github, gitea, npm):
|
||||
`claude-bottle-cred-proxy-<slug>`. The agent container starts
|
||||
after the sidecar is up so DNS resolution succeeds on the
|
||||
agent's first call.
|
||||
- **pipelock interop.** cred-proxy's outbound HTTPS still
|
||||
traverses pipelock — pipelock keeps its egress-allowlist role
|
||||
for the four upstream hosts. Drop `api.anthropic.com` from
|
||||
pipelock's TLS-MITM list (cred-proxy is now the trust endpoint
|
||||
for that host); the host stays on the plain HTTPS allowlist.
|
||||
- **pipelock interop.** cred-proxy's outbound HTTPS traverses
|
||||
pipelock: the sidecar's environ sets `HTTPS_PROXY` /
|
||||
`HTTP_PROXY` to the per-bottle pipelock URL, and the cred-proxy
|
||||
image's entrypoint runs `update-ca-certificates` over the
|
||||
per-bottle pipelock CA (`docker cp`'d into
|
||||
`/usr/local/share/ca-certificates/pipelock.crt` before start)
|
||||
so cred-proxy's HTTPS client trusts pipelock's bumped certs.
|
||||
Pipelock's allowlist + body scanner therefore apply to
|
||||
cred-proxy → upstream the same way they apply to direct agent
|
||||
traffic. Only `api.anthropic.com` stays on
|
||||
`passthrough_domains` (its bodies are LLM conversation text
|
||||
that legitimately trips DLP heuristics); github / gitea / npm
|
||||
hosts are auto-added to the allowlist (so cred-proxy can reach
|
||||
them) but NOT to passthrough, so pipelock body-scans them.
|
||||
- **Smart-HTTP push refused.** cred-proxy returns 403 for paths
|
||||
matching `/info/refs?service=git-receive-pack` and any path
|
||||
ending in `/git-receive-pack`. Fetch (upload-pack) is allowed.
|
||||
Push must go through `bottle.git` / git-gate, where the
|
||||
gitleaks pre-receive hook runs. This holds even when no
|
||||
matching `bottle.git` entry exists — the proxy is not a
|
||||
scanned-push path, period.
|
||||
- **Plan rendering.** `bottle_plan.py` and the y/N preflight
|
||||
show: which tokens are configured (kind + ref name, not the
|
||||
value), the proxy port, the routes the proxy will publish.
|
||||
|
||||
Reference in New Issue
Block a user