1
0
Fork 0

docs(plan): scope Session H — 0.3.1 regression fix for active-content calibration

v0.3.0 makes the untrusted upload path refuse ordinary documents. Measured on
both doors under PRESET_USER_UPLOAD: one ordinary markdown image reaches
fail_secure, one ordinary link/autolink/refdef reaches quarantine_review, and
only a document with no external references persists.

Root cause is three independent defects that compound. Severity tracks
construct type rather than URL shape, so every external image is HIGH when the
exfiltration primitive is actually a URL that carries data outward. The
quarantine floor fires on any finding at all, a premise that broke once every
link became a finding. And the false-positive corpus could not have caught
either: it holds no markdown links or images, asserts only under
PRESET_TRUSTED_SOURCE where everything warns anyway, and runs _scan_input, so
the output gate where active_content lives is never exercised by it.

Both code changes are required together -- verified that fixing severity alone
still quarantines via the floor, and fixing the floor alone still fail-secures
on a HIGH image.

Records the version reasoning too: 0.3.1 is honest as a patch because the
lexicon carries no LOW/INFO patterns (40 high, 22 medium, 21 critical) and no
other detector emits LOW, so raising the floor to MEDIUM+ is a no-op for every
finding that existed before 0.3.0. The new middle preset stays out of this
release; it is additive API and belongs in 0.4.0.
This commit is contained in:
Kjell Tore Guttormsen 2026-07-25 15:11:12 +02:00
commit da7421e6c8

View file

@ -257,6 +257,82 @@ Nøkkelantakelser (+ test) · Verifisering. Testkommando alltid:
---
### Session H — 0.3.1: regresjonsfiks for aktivt-innhold-kalibrering *(HASTER — går FORAN G)*
- **Mål:** gjøre den utrustede upload-stien brukbar igjen uten å miste EchoLeak-
deteksjonen, og lukke testgatens blindfelt som slapp regresjonen forbi 522 grønne tester.
- **Utløser:** `llm-ingestion-okf` projiserte konsekvensen fra CHANGELOG-teksten FØR
0.3.0 ble kuttet; vi shippet før vi leste innboksen. De traff retningen og
undervurderte alvoret.
**Målt på v0.3.0 (ikke antatt) — begge dører, `PRESET_USER_UPLOAD` / `origin=EXTERNAL`:**
| dokument | utfall |
|---|---|
| ingen lenker | `warn` |
| én ordinær lenke / autolink / refdef | `quarantine_review` |
| **én ordinær bilde-referanse** | **`fail_secure`** |
| relativt/lokalt bilde | `warn` |
- **Rotårsak — tre UAVHENGIGE defekter som forsterker hverandre:**
1. **Severity følger konstruksjons-TYPE, ikke URL-FORM.** `markdown-image: HIGH` fyrer
på ethvert eksternt bilde. Exfil-primitivet er ikke «et bilde» — det er en URL som
*bærer data utover*. `![diagram](https://example.com/a.png)` bærer ingenting.
2. **Quarantine-floor fyrer på ENHVER finding** (`policy.quarantine_default and
report.found`). Premisset «findings er unntaket» brøt da hver lenke ble en finding.
Dette er den allerede dokumenterte «vakuøs quarantine-floor»-residualen.
3. **FP-korpuset kunne strukturelt ikke fange det:** `_FALSE_POSITIVE` (6 prosa-snutter)
har NULL markdown-lenker/bilder; asserteres KUN under `PRESET_TRUSTED_SOURCE` (hvor
alt gir `warn` uansett); og kjører `_scan_input`, så `scan_output` steg 6 — der
`active_content` faktisk bor — berøres aldri av korpuset.
- **Begge kodeendringer trengs sammen (verifisert):** kun (1) → floor karantenerer
fortsatt; kun (2) → HIGH-bilde fail_secure'er fortsatt.
- **Scope-grense:** INGEN ny offentlig API. **Ny mellom-preset er 0.4.0, ikke denne.**
Rør ikke trusted-tier-residualen (HIGH-i-trusted→WARN). Ingen omskriving/neutralize i
gaten — biblioteket reparerer ikke stille (bekreftet som bærende av okf).
- **Avhengigheter:** ingen.
- **Filer:** `calibration.py` (alle nye tall — låst konvensjon), `active_content.py`
(form-analyse), `disposition.py` (floor-terskel), `tests/test_corpus.py` (blindfeltet),
`tests/test_active_content.py`, `coverage.py`, `CHANGELOG.md`, `docs/LIMITATIONS.md`.
- **TDD-plan (failing test FØRST — Iron Law):**
1. Utvid `_FALSE_POSITIVE` med REALISTISKE markdown-dokumenter (ordinær lenke, bilde,
autolink, refdef, blandet) og legg til et FP-testtilfelle som kjører `screen_output`
under `PRESET_USER_UPLOAD`. **Dette skal være rødt før noen kildeendring** — det er
beviset på at gaten nå faktisk dekker regresjonen.
2. Form-analyse i `active_content`: ordinær ekstern URL (bar sti, ingen query, ingen
høy-entropi-segment) → LOW; exfil-form → behold HIGH/MEDIUM. Gjenbruk `entropy`-
modulen; ikke oppfinn ny heuristikk. `data-uri` og `raw-html` beholder HIGH
ubetinget (aktive uansett URL-form).
3. Floor-terskel i `_base_disposition`: fyrer på MEDIUM+ i stedet for enhver finding.
4. Adversarielt mot-korpus: exfil-formede URL-er (query som bærer verdi, høy-entropi
sti-segment/subdomene, percent/base64-payload) MÅ fortsatt nå HIGH → fail_secure.
- **Nøkkelantakelser (+ test):**
- *«0.3.1 er ærlig som patch, ikke minor.»* **VERIFISERT 2026-07-25:** lexicon har 0
LOW/INFO-mønstre (40 high / 22 medium / 21 critical) og ingen annen detektor
produserer LOW. Floor-endringen er derfor en **no-op for alt som fantes før 0.3.0**
den løsner ingenting for en v0.2.0-konsument. Re-test:
`python -c "…Counter(severity)…"` skal fortsatt vise null LOW/INFO.
- *«form-heuristikken har ikke falske negativer på ekte exfil.»* Test: mot-korpuset i
TDD-steg 4. **Dette er den farlige antakelsen** — en for grov «ordinær»-definisjon
gjenåpner EchoLeak.
- *«ren beaconing forblir udekket.»* Et bilde som kun trigger et fetch uten å bære data
(IP/metadata-lekkasje) faller til LOW. Dette er et BEVISST nytt hull og **skal skrives
inn i `docs/LIMITATIONS.md`**, ikke ties i hjel.
- **Verifisering:**
- `PYTHONPATH=src .venv/bin/pytest` → alle grønne (`-q` skjuler summary — dropp den).
- `python -m llm_ingestion_guard.coverage` → exit 0; ingen dokumentert gap-assertion
brutt, og de nye FP-tilfellene er representert i matrisen.
- Repro-tabellen øverst kjørt på nytt: ordinær lenke/bilde/autolink/refdef → `warn`
på BEGGE dører; exfil-formet bilde → `fail_secure` under upload-preset.
- Versjons-sync 0.3.0→0.3.1 i alle fire filer + README install-pin; anonym ren-venv
`pip install …@v0.3.1` før README averterer den.
- Coord til de 7 varslede repoene med MÅLINGER, ikke beskrivelse (vi lovet det).
---
## TRACK 2 — Node/TS-port (stream 3). Starter etter Session G.
**Ryggrad:** en delt **parity-fixture** (`fixtures/parity/*.json`: `input → forventede