llm-ingestion-pipeline-secu.../tests
Kjell Tore Guttormsen 78c9f2f7f1 feat(neutralize): opt-in pure defang of active-content output (TDD) [skip-docs]
Build-order step 6. Close the EchoLeak class (CVE-2025-32711): active content in
persisted model OUTPUT that a downstream renderer auto-fetches or makes clickable,
exfiltrating data zero-click. These carriers are neither injection strings nor
high-entropy, so lexicon + entropy miss them — a distinct control (OWASP LLM05,
Improper Output Handling).

Defang, don't delete. URLs in active-content position are rewritten to a
non-resolvable but auditable form (https://evil.com -> hxxps://evil[.]com;
data:/javascript: colon neutralized to [:]); raw active HTML is escaped so a
renderer shows inert literal text. Visible information survives review; only the
machine-actionable affordance dies. Dot-defang is idempotent (never [[.]]).

Six classes, each a Finding: markdown-image (HIGH, the zero-click primitive),
inline-link (MEDIUM), reference-link definition (MEDIUM, the documented
image-filter bypass), angle-bracket autolink (MEDIUM), raw active HTML (HIGH,
inherently-active tag OR event/URL attribute — benign <b>/<em> left untouched),
standalone data: URI (HIGH). Processing order prevents double-counting.

Opt-in and separate: calling neutralize() IS the opt-in to mutate; the report-only
gate stays pure (design principles 3 & 4). Byte-identical on clean output, mirror
of the sanitizer invariant. Scope conceded in the docstring: a targeted defanger,
not a full HTML sanitizer.

17 tests: byte-identity + FP guards (lone <>[], metadata:, benign HTML), image
defang + non-resolvability, secret-exfil URL, inline/reference/autolink, raw-html
escape + script neutralization, data: URI, no double-count, counts, source.

[skip-docs]: README positioning + honest-limitations remains the deliberate
build-order step-11 deliverable (steps 1-5 likewise left README frozen).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyRCQMocjZ6SmSQ6JidJ2k
2026-07-04 18:55:12 +02:00
..
test_entropy.py feat(entropy): high-entropy/encoded-blob detection with decode-and-rescan (TDD) 2026-07-04 09:43:24 +02:00
test_fence.py feat(fence): randomized unspoofable delimiter + attacker marker-strip (TDD) [skip-docs] 2026-07-04 18:23:35 +02:00
test_lexicon.py feat(lexicon): JSON injection lexicon + variant-set scan (TDD) [skip-docs] 2026-07-04 17:20:21 +02:00
test_neutralize.py feat(neutralize): opt-in pure defang of active-content output (TDD) [skip-docs] 2026-07-04 18:55:12 +02:00
test_report.py feat: scaffold package + report and sanitize modules (TDD) 2026-07-04 09:24:20 +02:00
test_sanitize.py feat: scaffold package + report and sanitize modules (TDD) 2026-07-04 09:24:20 +02:00