feat(orchestrator): github PAT via credential proxy — spawned agents push with zero raw PAT (#11536 E3) - #11977
Conversation
…push with zero raw PAT (#11536 E3) Non-model credential brokering: the E3 sibling of the E1/E2 model gateway. Coding sub-agents access github (and other non-model APIs) WITHOUT a raw PAT in their env — the PAT is injected outbound by the credential proxy; the agent gets a proxy redirection plus a scoped handle. Core (packages/core/src/features/credential-proxy): - client.ts: createCredentialProxyFetch — an HMAC-signed fetch wrapper mirroring @stwd/proxy-client semantics (header-only injection, agent-scoped bearer, a narrow per-host route allowlist with explicit method + path prefix). Off-list targets are rejected before any network call. The transport to the proxy goes through the SSRF guard with the trusted proxy host allowlisted. - config.ts: vendor-neutral ELIZA_CREDENTIAL_PROXY_URL / _TOKEN / _SIGNING_KEY / _STRICT / _ROUTES (mirrors the ELIZA_MODEL_GATEWAY_* convention). Both-or- nothing mode gate; malformed routes override fails closed. Orchestrator (plugin-agent-orchestrator): - credential-proxy-env.ts: a dependency-free git credential helper (materialized at spawn) that brokers auth through the proxy so `git push` needs no PAT in env; applyCredentialProxyEnv deletes every raw VCS PAT and points the child's git at the helper via GIT_CONFIG_*. Fail-closed strict mode refuses the spawn when a raw PAT is present on the box. - acp-service.ts buildEnv: a separate, clearly-commented credential-proxy block after the E2 model-gateway block (distinct env keys — the two #11536 lanes never touch the same lines). Tests (22): proxy client signs + forwards correctly and rejects off-allowlist hosts; config gate + strict; the git credential helper run by the REAL node binary against a REAL mock proxy returns broker-minted creds with a valid HMAC signature and no PAT, and fails closed for off-allowlist hosts; the real AcpService.buildEnv spawn seam yields a child env with no raw PAT; strict mode refuses to spawn with a PAT on the box; helper↔core signing lockstep cross-check. A real end-to-end push against a live broker is a documented follow-up (no broker reachable here); the proxy endpoint is mocked with a real HTTP server. Refs #11536 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
QA review (orchestrator/security, E3 companion to the merged #11979 E2): sound design. applyCredentialProxyEnv deletes every raw VCS PAT (GITHUB_TOKEN/GH_TOKEN/GH_ENTERPRISE_TOKEN/GITHUB_PAT) from the child env and points git at a dependency-free (node-builtins-only) credential helper that fetches broker-minted creds at push time via an HMAC-signed proxy request; the per-host route allowlist (host+method+path) rejects off-list targets before any network call, and the proxy transport goes through the core SSRF guard with the trusted proxy host explicitly allowlisted. Fail-closed strict mode refuses to spawn with a PAT on the box; opt-in both-or-nothing config gate. The core credential-proxy module is a new isolated feature; index.node.ts export is purely additive (zero removed lines); the E3 env block is distinct keys from E2 so the lanes merge cleanly (verified merge-clean). Verified on the head: core credential-proxy 13/13; orchestrator credential-proxy-env 9/9 after rebuilding core dist (the initial red was stale-dist resolution of the new @elizaos/core exports, not a defect) — includes the real-node-helper-vs-real-mock-proxy HMAC test and the off-allowlist fail-closed case. Merging. |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
What / why
Phase E3 of #11536 (credential-broker integration, Priority:High/security): coding sub-agents access github (and other non-model APIs) without a raw PAT in their env. The PAT is injected outbound by the credential proxy; the agent gets a proxy redirection + a scoped handle. This is the NON-MODEL sibling of the merged E1 (#11660) / E2 (#11651) model-gateway path.
Acceptance (issue E3): a spawned sub-agent pushes a branch with zero PAT in its env. Met — the child env in proxy mode carries no raw PAT and git obtains a broker-minted credential at push time via a credential helper.
Deliverables
1. Credential-proxy client util (
packages/core/src/features/credential-proxy/)createCredentialProxyFetch— an HMAC-signedfetchwrapper mirroring@stwd/proxy-clientsemantics: header-only injection (agent-scoped bearer, never the raw credential), a narrow per-host route allowlist (explicit host + method + path prefix), off-list targets rejected before any network call. The transport to the proxy runs through the existingpackages/core/src/networkSSRF guard with the trusted proxy host explicitly allowlisted (a private/localhost sidecar must not be blocked, while redirects/DNS-rebind stay guarded).ELIZA_CREDENTIAL_PROXY_URL/_TOKEN/_SIGNING_KEY/_STRICT/_ROUTES, matching the E1/E2ELIZA_MODEL_GATEWAY_*naming. Both-or-nothing mode gate; a malformed routes override fails closed.2. Git credential-helper bridge — a dependency-free Node helper (node built-ins only, so it runs inside a child agent that may not resolve
@elizaos/core), materialized at spawn. On gitgetfor an allowlisted https host it POSTs a signed request to the proxy's/git-credentialendpoint and returns the broker-mintedusername/passwordto git. Signing stays byte-for-byte in lockstep with core's canonical scheme (pinned by a cross-check test).3. Orchestrator wiring (
plugin-agent-orchestrator)applyCredentialProxyEnv: deletes every raw VCS PAT (GITHUB_TOKEN/GH_TOKEN/GH_ENTERPRISE_TOKEN/GITHUB_PAT) from the child env and points the child's git at the helper viaGIT_CONFIG_*. Fail-closed strict mode refuses to spawn when a raw PAT is present on the box.AcpService.buildEnv: a separate, clearly-commented credential-proxy block after the E2 model-gateway block — distinct env keys, so the two credential-broker integration: keyless model + tool credentials for agents and orchestrated sub-agents (gateway base-url, scoped leases, credential proxy) #11536 lanes never touch the same lines and merge cleanly.Tests (22, all green locally)
Core (13): sign + forward correctness (independently recomputed HMAC), per-host allowlist rejects off-list host/method/path before any call, no-signing-key path, body-hash determinism, config gate + strict + routes-override fail-closed.
Orchestrator (9):
applyCredentialProxyEnvscrub + inject; strict throws; the git credential helper run by the REAL node binary against a REAL mock proxy HTTP server returns broker-minted creds with a valid HMAC signature and no PAT, and fails closed for an off-allowlist host (no proxy call, non-zero exit); the realAcpService.buildEnvspawn seam yields a child env with no raw PAT + helper wiring; strict mode refuses to spawn with a PAT on the box; helper↔core signing lockstep cross-check.bun run typecheck(orchestrator) clean; biome clean.Evidence / follow-up
/git-credentialendpoint is exercised end-to-end against a real local HTTP mock proxy (realnoderuns the helper, real HMAC verified server-side). A push against a live broker is a documented follow-up — no broker is reachable in this environment.Refs #11536
🤖 Generated with Claude Code