Repository navigation
v0.20.1 — gh in broker sessions + four broker regressions fixed (#65)
Patch release: a small feature (gh authenticates through the broker) and
four fixes that restore brokered authentication in real sessions — read the
Security entry.
Fixed
ghworks in broker sessions (#65). With a GitHub-covering broker the
cage wired a placeholder git helper but gave theghCLI nothing, so
gh api/gh pr …failed with "not logged in" in exactly the sessions
where GitHub access is brokered — and the only workaround wasgh auth login, minting a real long-lived token into the cage (the ADR 0007
limitation). The entrypoint now decides, with the same shared matcher and
independently of the git decision, whether the broker covers
api.github.com:443, and if so exportsGH_TOKEN=tjor-broker-placeholder
into the agent environment;ghsendsAuthorization: token <placeholder>
and the proxy substitutes the real credential toward the covered host, as
it already did for git's Basic placeholder. Not covered (kube-only broker,
a host list naminggithub.comwithout a glob, no broker) leavesGH_TOKEN
unset. The default*.github.comcovers it.
Security
- Behavior change, called out:
ghprefersGH_TOKENover a stored
hosts.yml, so a token someone minted withgh auth logininside an
earlier session is no longer used in a broker session — the brokered
identity is the session's identity. Andgh auth loginrefuses to run
whileGH_TOKENis set, which removes the easy in-cage path to minting a
real token in such sessions. Honest scope: the agent can unset the variable,
so the ADR 0007 limitation is narrowed, not closed (ADR amended). - Caveat: a GitHub App installation token cannot read
/user, sogh auth statusmay report a failure while repo-scoped commands work (README). - Tests: the proxy unit test now covers gh's
tokenscheme; the live broker
integration test asserts theGH_TOKENplaceholder in a covered session
(secret scan unchanged) and the three coverage cases at direct invocation. - Four regressions found by the real-token end-to-end, fixed here.
(1) Proxy host-scoped decisions were keyed on the pinned IP. Since the
#41 resolve-and-pin (v0.17.4), mitmproxy reports the pinned upstream IP in
flow.request.hostfor every tunneled request, so the credential broker,
x-agent identity injection, the LLM-gateway key, the #62 secret scan and
the denial log compared an IP against hostnames and never matched a
DNS-resolved destination — git's and gh's placeholders were forwarded
unsubstituted and GitHub answered 401. The policy verdict used the
hostname, so requests were allowed and nothing looked denied; unit tests
model hostnames and the conformance broker probes run with the IP guard
off, so CI never saw it. Every such decision now keys on the client's SNI —
the hostname mitmproxy verifies the upstream certificate against, so a
forgedHostheader inside a tunnel to another server cannot attract a
credential (regression-tested both ways). (2) cplt sets
GIT_CONFIG_NOSYSTEM=1for the sandboxed harness, so under the
kernel-sandbox tier git ignored/etc/gitconfig— the placeholder helper,
the gh fallback, the SSH→HTTPS rewrites andsafe.directorytree trust,
all of it; the uid alignment masked the trust half. The child's environment
is now corrected inside the sandbox. (3) cplt's Landlock policy denies
reading/etc/gitconfig; the wrap grants exactly that file read-only.
(4) The injected scheme was wrong for git. The proxy injected
token <t>toward every covered host; GitHub's git smart-HTTP endpoint
accepts only Basic (x-access-token:<token>) and answers 401 totoken
andBearer, whileapi.github.comaccepts all three — so brokered git
auth never worked against real GitHub (ADR 0007's "GitHub accepts … as
token <t>" holds for the API only). The credential is now re-issued in
the scheme the client sent: git's Basic stays Basic, gh'stokenstays
token, Bearer stays Bearer. Verified end-to-end:gh api userand
git ls-remoteon a private repository both succeed from inside the
wrapped harness with only the placeholder in the cage.
The live broker test now asserts git's and gh's view from inside the
wrapped harness. Follow-up (not done): a conformance probe for injection
with the IP guard on needs a publicly resolvable echo target.