docs(design): legibility and the opaque box — why we embed an interpreter - #312
Open
hartsock wants to merge 1 commit into
Open
docs(design): legibility and the opaque box — why we embed an interpreter#312hartsock wants to merge 1 commit into
hartsock wants to merge 1 commit into
Conversation
…eter WHAT: adds docs/design/legibility-and-the-opaque-box.md, a position paper arguing the *value* case for the in-process shell engine, plus two framings absent from the docs: the `bash -c` opaque-box enumeration, and the observation that POSIX fds are already ocap-grade capabilities. WHY: ADR 0005 demoted L2 from authoritative to "convenience." That is correct as a security claim and should not be softened — but it left no written answer to "then why carry a forked brush engine instead of shelling out to /bin/bash inside the L3 jail?" This paper supplies that answer: enforcement and legibility are different products and only one of them is obtainable from `bash -c`, which returns stdout/stderr/exit code and nothing about what actually ran. Three contributions: - The opaque box. Enumerates what `bash -c` structurally cannot give a harness: resolved argv, sound approval, attribution, atomic admission, structured denial, checkpointing, replay. Names approval-by-string-matching as a category error of the same shape ADR 0002 already rejects in prompt hygiene. - Two axes, not a renumbering. L1/L2/L3 keep their ADR 0001/0005 meanings and answer "where does the guarantee rest?" A separate legibility / authority / enforcement triad answers "what is each part for?" and deliberately does not map one-to-one — authority (Caveats, meet) is orthogonal to the layers. Stated this way to protect I9 honesty and to keep us out of the documented failure mode: Safe.pm, Java SecurityManager, Python rexec, Node vm, Deno permission flags all shipped a legibility layer labelled as a boundary. - fds are already capabilities. Unix does not lack capabilities; it offers ambient authority alongside them. Yields a structural target property — a confined child obtains a resource only by inheriting a handle, never by pathname resolution against an ambient root — which is Capsicum, is what Landlock approximates (ADR 0009/0011), and explains why I6 is load-bearing: a handle has no check-time/use-time resolution gap, which is precisely where the dangling-symlink fs_write escape lived. No invariant moves and no enforcement claim changes. Documentation only. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
docs/design/legibility-and-the-opaque-box.md, a position paper supplyingan answer the docs currently lack.
ADR 0005 demoted L2 from authoritative to convenience. That is correct as a
security claim and this PR does not soften it. But it left no written answer
to the obvious follow-up: then why carry a forked brush engine at all, instead
of shelling out to
/bin/bashinside the L3 jail?The answer is that enforcement and legibility are different products, and only
one of them is obtainable from
bash -c— which returns stdout, stderr, and anexit code, and nothing whatsoever about what actually ran.
Three contributions, all absent from
docs/today (verified by grep: no hits for"opaque box", "bash -c", "file descriptor", "preopen", "Capsicum"):
The opaque box. Enumerates what
bash -cstructurally cannot give aharness: resolved argv, sound approval, attribution, atomic admission,
structured denial, checkpointing, replay. Names approval-by-string-matching as
a category error of the same shape ADR 0002 already rejects in prompt
hygiene —
eval,$(…),sh -c "$VAR", aliases andPATHshadowing defeatit, and no amount of pattern hardening fixes that.
Two axes, not a renumbering. L1/L2/L3 keep their exact ADR 0001/0005
meanings and answer "where does the guarantee rest?" A separate
legibility / authority / enforcement triad answers "what is each part
for?" and deliberately does not map one-to-one — authority (
Caveats,meet, the mint-tokenToolContext) is orthogonal to the layers rather thanbeing one of them. Stated this way specifically to protect I9 honesty and to
keep us out of the documented failure mode:
Safe.pm, JavaSecurityManager,Python
rexec, Nodevm, and Deno's permission flags each shipped alegibility layer labelled as an enforcement boundary, and each was bypassed.
fds are already capabilities. Unix does not lack capabilities — a file
descriptor is unforgeable, transferable and revocable, and fd-passing is ocap
delegation. The defect is that Unix offers ambient authority alongside them.
That yields a crisp structural target property: a confined child obtains a
resource only by inheriting a handle (fd or preopen), never by pathname
resolution against an ambient root. This is Capsicum, is what Landlock
approximates (ADR 0009/0011), and explains why I6 is load-bearing rather
than fussy — a held handle has no check-time/use-time resolution gap, which is
exactly where the dangling-symlink
fs_writeescape lived.Also reframes the ADR 0019 fork cost: the
brush-ocap-*fork is not overhead wetolerate for a weak second leash behind Landlock. Brush's real asset is not
bash compatibility — it is that
brush-core/brush-parserare libraries, soevery dispatch point becomes a hook. Compatibility is the ticket, not the prize.
Relates to #311 (quantitative ambient/OpenShell evaluation) — the "what is the
minimum effect surface an agent actually needs?" open question is that issue's
premise stated from the legibility side. Does not close it.
Test plan
Documentation only. No invariant moves, no enforcement claim changes, no code
touched —
docs/design/is the only path in the diff.memory. One error caught and fixed pre-commit: the canonicalization
invariant is I6 (canonicalize no-follow, then test containment), not I7
(no in-shell escape from the spawn funnel). I9 (no overclaiming), ADR
0001/0002/0005/0007/0009/0010/0011/0019 references all verified.
restate ADR 0001's layer model or ADR 0005's boundary decision.
git pushpre-push hook green end to end — clippy, tests, package dry-run,and the Tier-3 Lean formal gate (157 security theorems replayed, base
axioms clean).
Note
Low Risk
Documentation-only under
docs/design/; explicitly states no invariant or enforcement claim changes.Overview
Adds
docs/design/legibility-and-the-opaque-box.md, a position paper that answers why a forked embedded shell remains worthwhile after ADR 0005 treats L2 as convenience, not the security boundary. It does not weaken L3 or move invariants.The doc frames
bash -cas an opaque box (stdout/stderr/exit only) and lists what that structurally cannot provide—resolved argv, sound string-based approval, attribution, atomic admission, structured denial, checkpointing, replay—and ties string-matching approval to the same category error ADR 0002 rejects for prompt hygiene.It introduces an orthogonal legibility / authority / enforcement triad (distinct from L1–L3) so legibility and policy are not mislabeled as enforcement, with negative prior art (
Safe.pm, JavaSecurityManager, etc.). It reframesbrush-core/brush-parseras in-process hooks (compatibility as adoption cost, inspectability as the prize) and adds an fd-as-capability / ambient-vs-handle lens for L3 (Capsicum, Landlock, I6, WASI preopens) plus open questions tied to #311.Reviewed by Cursor Bugbot for commit d4c892f. Configure here.