Reading is defensive
- Source files are opened read-only, with
O_NOFOLLOW, and re-checked for change while being read. - Symlinks get one of three outcomes: resolved inside a declared root, recorded as crossing between roots, or refused and listed. Never a silent skip.
- Never-export rules keep whole classes of data out of any artifact: account and billing identity, machine fingerprints, trust decisions, OAuth locks, transcripts, history.
Redaction runs as five layers
The results are unioned, so a value caught by any layer is redacted:- Declared secret positions, per surface.
- Key names.
- Clean-room provider patterns.
- Entropy at declared sinks.
- A deep walk of every parsed leaf, with one bounded decode.
5 and nothing is written. There is no --include-secrets and no second
“complete” file.
The honest limit — shapeless high-entropy secrets with nothing naming them
are caught only by position. Detection is defence in depth, not a guarantee;
read a bundle before you share it. The redaction report tells you exactly what
was found, the class assigned to each value, and the confidence.
Imported bundles are hostile input
Entry names are canonicalized and re-checked on read. Traversal, case-fold collisions, duplicate entries, count and size bombs and tampered digests are refused with distinct exit codes rather than repaired. The import path is built so that consent is specific and revocable:- Nothing is applied without a recorded consent against a specific rendered diff.
- Permission rules are additions; importing rule 3 resolves to an append and can never overwrite yours.
- Everything executable lands written but inert, in the runtime’s own disabled
idiom:
"disabled": true,enabled = false, ahooks_disabledblock, no execute bit.enableis a separate act that re-verifies the content hash recorded at import. - Writes are staged at
0700, snapshotted, fingerprint-re-verified immediately before each write, made throughO_NOFOLLOW | O_EXCLtemp files plusrename, and rolled back in full on any failure.
What the tests hold down
The named release gates each pin one property, and a failure names the property that broke:gate:purity (no I/O modules in the core), gate:secrets (the
seeded-credential recall floor), gate:network (the stubbed-network cycle),
gate:adversarial (hostile bundles), gate:noop (diff leaves the target
home byte-identical), gate:compat, and gate:cutover. Every test runs
against a committed fake home; nothing in the suite reads a real ~/.claude,
~/.codex or ~/.claude.json.