v0.1.1
0.1.1 (2026-07-29)
Boundary Hardening
- Refused network stdio: The launcher now refuses execution if
stdin,stdout, orstderrare network sockets, regardless of manifest egress grants. This closes socket-inheritance bypasses where a sandboxed process could communicate over pre-opened network file descriptors without passing through the host proxy. - Refused
write: /: Manifest validation now rejects a write grant of the root directory (write: /) outright. - Fail closed on non-amd64 architectures: The seccomp filter now explicitly refuses execution on non-amd64 architectures rather than quietly skipping the seccomp architecture guard.
- Fail closed on proxy & NAT64 failure: The HTTP CONNECT egress proxy fails closed (refuses connection) when NAT64 prefix discovery cannot answer, when RFC 6052 address layout is invalid, or when NAT64 translation fails to derive a target.
- Fail closed on unwalkable credential paths: Credential alias resolution and home directory traversal fail closed when directory walking cannot complete due to permission errors or unreadable paths.
- Expanded default shields: Added
.claude.json.backupto default credential denylist shields and ensured relocatedXDG_RUNTIME_DIRpaths are shielded across all user anchors. - Normalized proxy hostnames: Trailing DNS root dots (e.g.
example.com.) in HTTP CONNECT targets are stripped before matching against manifest host rules.
Boundary & Information Disclosure Fixes
- Proxy refusal privacy: Proxy refusal bodies no longer disclose resolved destination IP addresses to the sandboxed caller.
- Embedder observer protection: Embedder observer panic handling prevents proxy panics from disrupting host enforcement.
- Standardized guard refusal: Guard-blocked connection attempts return standard dial failure responses rather than disclosing internal gate errors.
Profiling & Observability (bento profile)
- Entry-stop syscall decoding: Syscall pathnames and
execveevents are now decoded at entry stops rather than exit stops, preventing missed system calls (such asexecveat) and eliminating false phantom drop counts. - Thread probe accounting: Fixed probe leak and drop accounting during thread termination,
execvethread retirement, and root exit. - Credential alias scanning in profiling:
bento profilenow executes credential alias scanning to detect foreign-home credential stores during profiling runs.
Operator Surface & Platform Refinements
- Surfaced guard blocks: Operator and supervisor summaries now report destinations blocked by network guards.
- Landlock degraded tier: Added
resolve_unixhandling to Landlock's degraded tier and stopped requesting ungranted Landlock rights. - Shield mount cleanup: Shield mount points created during a sandbox run are explicitly reclaimed upon exit.
Changelog
- add0fcb: build: run the example modules under make check (@whiskeyjimbo)
- a324595: feat(credhunt): hunt a real home for unshielded credential shapes (@whiskeyjimbo)
- f001a42: feat(landlock): handle resolve_unix in the degraded tier (@whiskeyjimbo)
- a3ef0a6: feat(proxy): surface guard-blocked destinations to the operator (@whiskeyjimbo)
- a7f0683: fix(alias): refuse a credential walk that could not finish (@whiskeyjimbo)
- b2e24d2: fix(alias): skip an anchor with no file behind it (@whiskeyjimbo)
- 815a0dd: fix(cli): quote host paths in the resolved-target lines (@whiskeyjimbo)
- e08ab76: fix(cli): quote the grant name and the shield anchors too (@whiskeyjimbo)
- e4d91a7: fix(credhunt): refuse an unwalkable home instead of reporting clean (@whiskeyjimbo)
- 37bb396: fix(denylist): key the file-relocation store check on every anchor (@whiskeyjimbo)
- e26a460: fix(denylist): shield a relocated XDG_RUNTIME_DIR (@whiskeyjimbo)
- d6d3fd6: fix(denylist): shield the suffix-less .claude.json.backup (@whiskeyjimbo)
- 2bc086a: fix(denylist-audit): fail when a scope keyword stops matching (@whiskeyjimbo)
- 9e535c6: fix(embed): render the shielded grant's bound store (@whiskeyjimbo)
- a0d98d2: fix(landlock): stop handling rights no rule grants (@whiskeyjimbo)
- 529b14e: fix(launcher): claim a layer only for a run that reached its target (@whiskeyjimbo)
- cc27ba4: fix(launcher): examine every stdio descriptor before waiving one (@whiskeyjimbo)
- 67e5594: fix(launcher): keep the unreached-target record from lying either way (@whiskeyjimbo)
- 0cedbe9: fix(launcher): make the bridge's death report reachable (@whiskeyjimbo)
- 3a17fca: fix(launcher): refuse network stdio whatever the egress grant (@whiskeyjimbo)
- b8953cc: fix(launcher): report an in-sandbox bridge that stopped serving (@whiskeyjimbo)
- a623b1f: fix(launcher): warn only when a socket is really on stdio (@whiskeyjimbo)
- 206a4e6: fix(linux): bound the wait on the bridge liveness pipe (@whiskeyjimbo)
- 9ebeedf: fix(linux): claim only the shield artifacts the run creates (@whiskeyjimbo)
- 0aeb51f: fix(linux): reclaim the file shield mount points a run creates (@whiskeyjimbo)
- a0878e9: fix(linux): refuse an observation report whose status is unreadable (@whiskeyjimbo)
- 7e2d1cc: fix(linux): refuse write:/ in the shared grant checks (@whiskeyjimbo)
- 9a1d343: fix(linux): report an unanswered host probe as unknown (@whiskeyjimbo)
- a33932a: fix(linux): run the credential alias scan on the profiling path too (@whiskeyjimbo)
- 2f4ff8e: fix(observe): count a dead thread's held probe once (@whiskeyjimbo)
- f2575e4: fix(observe): count a probe lost with a dying thread (@whiskeyjimbo)
- ed9336d: fix(observe): count an unreadable stop's held probe once (@whiskeyjimbo)
- 2344e02: fix(observe): count execve at the entry stop, so execveat is not one (@whiskeyjimbo)
- 047c518: fix(observe): count probes held when root exits (@whiskeyjimbo)
- 5efb5c0: fix(observe): count what the retired leader thread held (@whiskeyjimbo)
- d18eb19: fix(observe): decoder accuracy pass over the phantom and missing paths (@whiskeyjimbo)
- 658da53: fix(observe): exempt futimesat's NULL pathname like utimensat's (@whiskeyjimbo)
- e8b85f0: fix(observe): forget a tid retired by an execve (@whiskeyjimbo)
- 26a3a9d: fix(observe): read pathnames at the entry stop, not the exit stop (@whiskeyjimbo)
- e412662: fix(observe): resolve a dead thread's phantom drops (@whiskeyjimbo)
- 2cbb7ec: fix(observe): stop counting a dead thread's entry stop (@whiskeyjimbo)
- 7a1cb47: fix(observe): stop counting signal returns as lost file accesses (@whiskeyjimbo)
- 0a50e7e: fix(pathresolve): return the input at the depth cutoff, not a mid-chain hop (@whiskeyjimbo)
- b9acc39: fix(profile): key foreign-home warnings on the run's anchors (@whiskeyjimbo)
- febfaf1: fix(proxy): answer a guard block as an ordinary dial failure (@whiskeyjimbo)
- 123ec09: fix(proxy): contain an embedder observer panic (@whiskeyjimbo)
- 8bbe7b1: fix(proxy): fail closed on a NAT64 answer that derives nothing (@whiskeyjimbo)
- 032ad41: fix(proxy): fail closed when NAT64 discovery cannot answer (@whiskeyjimbo)
- 532f3cb: fix(proxy): keep a mid-run Accept failure across the drain (@whiskeyjimbo)
- bc444ad: fix(proxy): stop refusal bodies disclosing the resolved address (@whiskeyjimbo)
- b1e64f3: fix(proxy): strip the DNS root label from a CONNECT target (@whiskeyjimbo)
- adaf6af: fix(proxy): validate the RFC 6052 layout before an 8215 verdict (@whiskeyjimbo)
- 8919820: fix(seccomp): refuse off amd64 rather than skip the arch guard (@whiskeyjimbo)
- bd9db19: fix(supervise): report the guard-blocked destinations too (@whiskeyjimbo)
- 806dc49: refactor(denylist): share one path-coverage predicate (@whiskeyjimbo)