Repository navigation
v0.20.4 — Review follow-ups: one workspace resolver, bounded tripwire, GH_TOKEN unset, mint-after-refusal
Review follow-ups for v0.18.16 → v0.20.3 (external review of the batch; the
three Highs and every Medium below were confirmed against the code before
fixing).
Security
- One guarded workspace resolver for every host-side consumer (v0.20.2
review, High). v0.20.2's core.worktree check guardedresolve_session
only; the identicalgit rev-parse --show-toplevelsat unguarded in
tjor attach(short-name qualification — a planted redirect could attach
the terminal to another repo's running agent when short names collide),
inrepo_root(the trusted repo policy/config behindtrust,init,
policy— a redirect could show the wrong path's policy to the operator's
informed-consent review) and indoctor.workspace_toplevel()now does
the cross-check once and everything resolves through it; the redirect
section of the launcher test covers attach and repo_root. The message no
longer suggests unsettingcore.worktreewhen none is set (it names
GIT_DIR/GIT_WORK_TREEinstead);nearest_git_rootrefuses a relative
path. - The egress secret tripwire is bounded before decompression (v0.18.17
review, High). The scan readflow.request.content, which mitmproxy
transparently decompresses — a ~1 MB gzip request body (under
stream_large_bodies) toward a scanned host could inflate to a gigabyte in
the shared proxy sidecar beforescan_max_bytesapplied: a decompression
bomb against the session's only egress. The scan now reads the wire bytes,
caps them, and inflates gzip/deflate with zlib'smax_length(output
capped regardless of ratio); brotli/zstd bodies are forwarded unscanned,
like streamed bodies. Tests: a 50 MB bomb yields at most the cap; gzip
bodies are still scanned; the scan site keys on the SNI after the pin. GH_TOKENis explicitly unset when the broker does not cover the API
host (v0.20.1 review, High). The comment said "left unset"; now the code
enforces it, so an ambient token (a directdocker run -e GH_TOKEN=…, an
image-baked value) never rides into the cage un-brokered. Live test:
kube-only broker + ambient token → unset.- Credential material is minted after every refusal (v0.19.0 review,
Medium).cmd_runresolved the session and minted broker material
before the--dir/--dir-rogates and the self-mount guard ran, so a
refused launch could leave a real PAT / GitHub App key / live kube token on
disk, invisible totjor ls/gc. The mint now runs last; the launcher
test asserts a refused--dirleaves nobroker.json(with a control). ssl_insecurefails closed at proxy startup (v0.20.1 review, Medium).
SNI-keyed injection is safe only because upstream certificates are
verified; the addon'sconfigurehook now shuts mitmproxy down if
ssl_insecureis ever set.
Changed
- Dropped the unused
TJOR_ALLOW_SELF_MOUNTexport (v0.20.0 review: dead
code implying a cage-side re-check that does not exist).self-install
swaps thecurrentsymlink atomically (rename over, no unlinked window). - Tests:
kinds_presentcovered for all six secret shapes; empty-secret and
bytes-SNI paths; the launcher test's redirect section comment now describes
the shipped design and its sections are in order.