Two changes that had to ship together, because they co-occur. `active:raw-html-link` (MEDIUM) splits the click-required carriers out of `active:raw-html`. The same URL was LOW as `[t](url)` and HIGH as `<a href="url">` — an asymmetry produced by syntax, not by affordance, on a carrier the markdown path has graded MEDIUM since 0.3.1. The event-handler test runs first, so `<a onclick=...>` stays HIGH. The url-attribute branch stays HIGH too: a name outside the active set has unknown rendering, and grading `<Card src=...>` as a link would be reasoning rather than measurement. The no-URL narrowing makes `</a>`, `<Frame>`, `<video />` and `<img alt=...>` without `src` inert — `<base />`'s argument from 0.6.0 applied to the rest of the name branch. It tests for the URL attribute's PRESENCE, not for a readable value, so the fail-secure gap `_url_attr_is_external` leaves open is not reopened here. WHY TOGETHER: the narrowing strips a document's `</a>`/`<Frame>` and what remains is the `<a href=...>` the split grades down, so each alone leaves the document blocked by the other's residue. `active_tag_class` is now the classification point and `is_active_tag` wraps it. The census patches the former: a boolean could only express a narrowing, never a regrade, so every carrier candidate would have measured equal to PRODUCTION — silently, and in the direction that reads as "no change helps". TWO COSTS, BOTH RECORDED RATHER THAN GLOSSED: - The split TIGHTENS the trusted tier. One finding becomes two, and >=2 findings at MEDIUM+ trip the compound overlay, so a document carrying both an `<img src>` and an `<a href>` goes WARN -> quarantine_review on PRESET_TRUSTED_SOURCE. On that preset it is the only direction the split can move anything. The census now reports a TIGHTENS column on both trust tiers against the previously shipped row — "frees N" without "tightens M" is a one-sided number. - `count` drops on documents containing `</a>`, a published field moving under a meaning that did not change. MEASURED: reference-corpus (389) 54 -> 53 fail_secure, tightens 0/0, and the census `PRODUCTION` row equals its `C1 + D` candidate row for row. The census also reproduces 133/3/13/108/25 exactly, so it is calibrated against every published historical number. The two wiki corpora are NOT yet re-measured; the tree says so explicitly in the docstring, LIMITATIONS and CHANGELOG rather than carrying probe numbers as fact. 791 tests (was 759), coverage 129/129, 6/6 documented gaps holding. Version bumped to 0.7.0 across every surface; no tag is set until the measurement lands.
3 KiB
llm-ingestion-pipeline-security
Kontekst
Gjenbrukbar, minimal defensiv layer for LLM ingestion-pipelines (write-time), til forskjell fra query-time chatbot-guardrails. Pakker det arkitektoniske kontraktet — sanitize → fence → tool-less karantenert transform → per-stadium capability-isolasjon → scan output før commit → fail-secure — som komponerbar, framework-agnostisk kode.
Referanse-implementasjon: claude-code-llm-wiki Stage B (tools/wiki_ingest/).
Lexikon-seed: injection-patterns.mjs fra llm-security-pluginen.
Repoet er på v0.7 (alpha): stdlib-kjernen er bygget og testet (15 moduler +
topp-nivå wiring, showcase + korpus), inkl. OKF-adapter og aktivt-innhold-
detektor (EchoLeak-klassen) i output-gaten. Mode-b import_bundle skanner
reserverte strukturfiler (index.md/log.md) i mottatte bundles i stedet for å
path-avvise dem; upload-front-end beholder shadow-reject (allow_reserved=False).
Output-gatens decode-and-rescan mater dekodet base64-klartekst gjennom BÅDE lexicon
og secret-egress (LLM02), så en base64-innpakket credential fanges som
decoded:egress:* i stedet for å forsvinne; hex-innpakket er en dokumentert
restgap (entropy eksponerer kun base64-klartekst). active:raw-html krever et
EKSTERNT mål på URL-attributt-grenen, og <base> er ute av det aktive navnesettet;
scanner og mutator har hver sin predikat (is_active_tag / is_defangable_tag).
Rå HTML graderes nå også på BÆRER: <a>/<area> er klikk-krevende og rapporteres
som active:raw-html-link (MEDIUM), og en tagg hvis hele affordans ER en URL den
ikke bærer (</a>, <Frame>, <video />) er inert. Klassifisering skjer i
active_tag_class; is_active_tag er en tynn wrapper, og census patcher den
FØRSTE (en boolsk patch kan ikke uttrykke en regradering).
ZWJ (U+200D) dømmes på KONTEKST, ikke identitet — unntas kun mellom to emoji, på
begge flater (sanitize eier predikatet, output importerer det).
Start med docs/BRIEF.md for design, README.md for bruk, docs/PLAN.md for
byggerekkefølgen.
Konvensjoner
- Norsk for dialog og planer, engelsk for kode og innhold (repoet er publisert).
- Ingen GitHub — kun Forgejo (
git.fromaitochitta.com). - Remote satt: offentlig
open/-speil på Forgejo; push hver commit (durabelt autorisert). - Minimal-dependency: stdlib-first kjerne; ML/judge-detektorer bak extras.
Communication patterns
Linking to local files
When pointing to local files in responses, always use markdown link syntax with a descriptive name:
- Use
[Human-friendly name](file:///absolute/path)— never barefile:///...URLs or autolinks<file://...>. - Always use absolute paths. Never
~/or relative paths. - For multiple files, render as a bullet list of named markdown links.
Why: bare file:// URLs only render the first as clickable across multiple lines. Named markdown links make each entry independently clickable and look cleaner.
Example: