diff --git a/docs/specs/2026-09-26-m5b-hardening.md b/docs/specs/2026-09-26-m5b-hardening.md index 0aeed4d..871cb32 100644 --- a/docs/specs/2026-09-26-m5b-hardening.md +++ b/docs/specs/2026-09-26-m5b-hardening.md @@ -146,13 +146,20 @@ ordinary tokens. **Patterns** are ported from Hermes' strict threat patterns (`hermes-agent`, `tools/threat_patterns.py`, MIT; attribution in the module and in `docs/dependencies.md`), whose rule is "match attack behaviour, not bossy English": instructions to ignore or replace earlier -instructions, to send data to a URL, to dump the conversation, to persist in SSH or agent +instructions, to send data to a URL, to dump the conversation, to persist in SSH configuration. M5a's six instruction phrases join this list: they flag from M5b on, where M5a refused. +The port (plan task 05, Hermes at `d0288be`) keeps seven of Hermes' rules and narrows those that +caught ordinary code work, because a recalled flagged note makes the reading session untrusted: +"dump the conversation" needs the object to end the clause, so "include the conversation id" +passes. Changes to agent configuration files are not a rule: Boxmaker's agent never loads +`AGENTS.md` or similar as instructions. `flag.rs`'s module comment lists every rule left out. + **Normalisation** before matching, written by hand with no new crate: lower case; full-width ASCII -folded to ASCII; runs of whitespace and zero-width characters collapsed; common leetspeak folded; -and about forty Cyrillic and Greek letters that look Latin mapped to them. +folded to ASCII; runs of whitespace collapsed to one space and zero-width characters dropped; +common leetspeak folded; about fifty Cyrillic and Greek letters that look Latin mapped to them +(from Unicode's confusables); and typographic apostrophes folded to `'`. **What a flag does**: the text is kept, one tier lower, and marked **untrusted**. That reuses what M5a has, with no new header or tag: @@ -165,7 +172,7 @@ M5a has, with no new header or tag: - `recall` returns such a note as `memory-tainted`, which makes the reading session untrusted. A flag never refuses and never loses text: the worst case of a false positive is a fact one tier -lower, which the owner can move back by hand. +lower, which the owner can move back by hand, and a session that recalls it marked untrusted. ### 6.4 The two corpora @@ -197,11 +204,12 @@ the corpora and review, and a typo cannot switch a rule off. ### 6.6 `bxctl sanitize check` `bxctl sanitize check ` (or the text on standard input) runs the three actions and prints -each rule that fires, and what it would do, writing nothing: +each rule that fires, and what it would do, writing nothing. A flag names only its rule: it +matches the normalised text, whose offsets do not map back to the input. ```text refuse secret-github ghp_… at 12 -flag exfil-url "send … to https://…" +flag exfil-url neutralise 1 tag ```