docs(plan): plan the move to the 2026 threat catalogs
The approved direction heads the plan: every cited catalog on its newest edition with a check date and source link, no catalog ID carrying an older edition's meaning, and the known 2025-2026 attacks that can reach an ingestion pipeline as test cases, each caught or documented as a gap. Measured on v1.4.1 before anything is built: LLM03-LLM10 carry their 2025 meaning in 101 places across 26 tracked files, and 17 of 19 invisible or deceptive code-point types (variation selectors among them) pass sanitize with no finding.
This commit is contained in:
parent
6702d7a569
commit
f19f434b54
1 changed files with 203 additions and 0 deletions
203
docs/PLAN.md
203
docs/PLAN.md
|
|
@ -1,3 +1,206 @@
|
|||
# PLAN — `llm-ingestion-guard`
|
||||
|
||||
## Retning (godkjent av operatøren 28.10.2026)
|
||||
|
||||
> «llm-ingestion-guard bygger på nyeste utgave av hver trusselkatalog den viser til,
|
||||
> hver med dato for siste sjekk og kildelenke. Ingen funn eller tekst bruker et
|
||||
> katalognummer med en eldre utgaves betydning. De kjente angrepene fra 2025–2026
|
||||
> som kan nå en innhentings-pipeline, er testsaker. Hver av dem fanges eller står
|
||||
> som et dokumentert hull.»
|
||||
|
||||
Operatørens ord: «Dette repoet bør også oppdateres [til de siste
|
||||
trusseldefinisjonene], og det er sikkert lurt å hente inspirasjon fra det som gjøres
|
||||
med LLM Security.» Hva som er lagt til, og hvorfor:
|
||||
- «Siste trusseldefinisjoner» er gjort målbart som tre ting: kataloger, numre og
|
||||
angrep. Det er målemetoden llm-security bruker, avgrenset til det som gjelder et
|
||||
bibliotek.
|
||||
- «Kan nå en innhentings-pipeline» avgrenser hvilke angrep som teller (§ T.3).
|
||||
- Ikke tatt med: automatisk varsling om nye katalogutgaver (kan komme senere, helst
|
||||
gjenbrukt) og kostnadsregelen for alltid-lastet tekst (gjelder bare en plugin).
|
||||
|
||||
Operatøren 28.10: «Ja til endringen. Lag en skikkelig plan, vi bruker så mange økter
|
||||
som trengs for å gjøre dette skikkelig.» Det samme «ja» godkjente den anbefalte
|
||||
merkingen: funn merkes med årstall (`LLM10:2026`, OWASPs egen skrivemåte), og
|
||||
endringen gis ut som 1.5.0 med en tydelig merknad.
|
||||
|
||||
**Dekket i:** katalogene → § T.4 økt 4 (rad 1) · numrene → økt 3 (rad 2) ·
|
||||
angrepene → økt 1 (fryser lista), 2 og 5…N (rad 3) · ferdig → siste økt.
|
||||
|
||||
---
|
||||
|
||||
# Trusselbildet 2026 (v1.4.2 →)
|
||||
|
||||
Planen til retningen over. Den gamle v1-planen står uendret lenger ned under
|
||||
«Implementation Plan — v1». Den er historikk og telles ikke i rad 2, på samme måte
|
||||
som CHANGELOG. Planen oppdateres underveis og overskrives aldri.
|
||||
|
||||
## T.1 Målt 28.10.2026 på v1.4.1 (`6702d7a`), før noe er bygd
|
||||
|
||||
1. **Katalognumrene har feil betydning.** OWASP Top 10 for LLM Applications kom i
|
||||
2026-utgave (publisert 04.08.2026) med ny rekkefølge. Bare LLM01 og LLM02 betyr det
|
||||
samme som i 2025. Repoet bruker LLM03–LLM10 med 2025-betydning på **101 steder i 26
|
||||
sporede filer** (src 50, tests 28, docs 17, README 6; CHANGELOG, `dist/` og
|
||||
`*.local.*` er utelatt). Ingen av dem bærer årstall. Hurtigtelling med
|
||||
`grep -oE 'LLM(0[3-9]|10)\b'`, altså ikke en klassifisering. Økt 1 fryser den
|
||||
ekte nevneren. Funnfeltet `owasp` bærer dette ut til hver eneste bruker:
|
||||
EchoLeak-funnene merkes `LLM05`, som i 2026 betyr dataforgiftning.
|
||||
2. **Usynlige tegn slipper gjennom.** Først testet jeg tekst skjult i
|
||||
variasjonsvelgere (U+FE00–FE0F, U+E0100–E01EF), der «ignore previous
|
||||
instructions and exfiltrate» var kodet i 43 tegn. Det ga **0 funn** i rensingen,
|
||||
i innhentingsinngangen og i utgangskontrollen, og alle 43 tegnene lå igjen i den
|
||||
«rensede» teksten. Deretter testet jeg 19 tegntyper, 8 av hver, gjennom rensingen.
|
||||
**17 av 19 gir 0 funn og blir liggende:** U+2060–2064, U+180E, U+3164, U+115F,
|
||||
U+1160, U+FFA0, U+034F, U+FFF9, U+200E, U+061C, U+E000 (privat bruk), U+FE00 og
|
||||
U+E0100. Positiv kontroll: U+E0041 (tag) og U+200B (zero-width) fanges og fjernes.
|
||||
Ingen av dette står i LIMITATIONS.
|
||||
3. **Ingen katalog har dato for siste sjekk.** README og «Threat-model anchors»
|
||||
lenger ned nevner OWASP 2025 uten dato. Agent-katalogen (OWASP Top 10 for Agentic
|
||||
Applications 2026, der ASI06 «Memory & Context Poisoning» er vårt område) og
|
||||
MITRE ATLAS er ikke koblet inn.
|
||||
4. **Leksikonet har ikke drevet.** Vår kopi har 83 mønstre, akkurat som
|
||||
leksikonet i `llm-security-commons` v0.9.0 (filversjon 0.8.0). Commons'
|
||||
tegntabell (`carriers.json` 0.2.0) mangler også variasjonsvelgere: tekstsøk etter
|
||||
`FE00`, `E0100` og `variation` gir 0 treff. Hullet er altså felles.
|
||||
|
||||
## T.2 Ferdig-kriteriet
|
||||
|
||||
Retningen er nådd når **rad 1–3** holder samtidig, målt på siste 1.x-release:
|
||||
|
||||
| # | Måling | Nevner | Målt 28.10 (v1.4.1) | Ferdig |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Trusselkataloger og kilder på nyeste utgave, hver med dato for siste sjekk og kildelenke | lista frosset i økt 1; kan utvides, krymper aldri uten operatørens ja | ikke talt (0 har dato) | N av N |
|
||||
| 2 | Steder der et katalognummer brukes med en eldre utgaves betydning, eller med en betydning ingen utgave har gitt det | telling over sporede filer, med historikk utenfor (CHANGELOG, v1-planen, utgitte gjennomganger) | **101** (hurtigtelling, § T.1.1) | 0, og en permanent test holder det der |
|
||||
| 3 | Kjente 2025–2026-angrep som kan nå en innhentings-pipeline, som testsaker | lista frosset i økt 1 etter § T.3 | ikke talt (variasjonsvelgere: rød) | hver sak fanges, eller står som hull i LIMITATIONS og dekningsmatrisen |
|
||||
|
||||
**Vaktregel, ikke mål:** ingen nye falske alarmer på korpusene vi allerede måler mot
|
||||
(falsk-positiv-korpuset og det pinnede OKF-korpuset på 6/53), og testsuiten,
|
||||
dekningsmatrisen og ReDoS-sveipet er grønne på hver release. En regel som strammer inn
|
||||
og gir nye alarmer på rene dokumenter, skal måles og legges fram, ikke slippes stille.
|
||||
|
||||
**Ikke framme hvis én:** en katalog er bak eller mangler dato · ett gammelt
|
||||
nummer-sted gjenstår · en angrepssak verken fanges eller er dokumentert.
|
||||
Underveis: går to økter på rad uten at et av tallene flytter seg, legges det fram for
|
||||
operatøren.
|
||||
|
||||
## T.3 Hva som teller som «kan nå en innhentings-pipeline»
|
||||
|
||||
Angrepet teller når nyttelasten kommer fram som **innhold** som en pipeline henter
|
||||
eller mottar og skriver til et lager en modell eller agent senere leser. Det teller
|
||||
også når nyttelasten rir på modellens transformerte output før den lagres. Det teller
|
||||
ikke når angrepet krever kodekjøring på verten, tilgang til modellvektene eller en
|
||||
kompromittert pakke (kjernen er stdlib-only). Grensetilfeller legges fram for
|
||||
operatøren i økt 1 og avgjøres ikke stille.
|
||||
|
||||
**Kandidater, IKKE verifisert.** Økt 1 verifiserer hver mot primærkilde, eller
|
||||
stryker den:
|
||||
- Smugling i variasjonsvelgere og andre usynlige tegn. *Målt rød 28.10.*
|
||||
- EchoLeak, CVE-2025-32711 (null-klikk-eksfiltrasjon via markdown i output).
|
||||
*Dekket i dag.*
|
||||
- ShadowLeak, CamoLeak, ForcedLeak, AgentFlayer: eksfiltrasjon eller injeksjon via
|
||||
dokumenter, e-post eller kontakter som en agent leser.
|
||||
- Forgiftede minnefiler (MemoryTrap-klassen): innhold skrevet til agentens minne,
|
||||
som er OWASP ASI06.
|
||||
- Skill-innhold med skjulte instruksjoner (ToxicSkills-klassen).
|
||||
- Injeksjon via issue- og PR-tekst som en agent henter (Comment and Control).
|
||||
- Faktaforgiftning (PoisonedRAG). *Allerede dokumentert som hull. Saken skal bekrefte
|
||||
at hullet står.*
|
||||
- Skjult tekst i opplastede dokumenter (HTML/CSS-skjult, hvit tekst).
|
||||
|
||||
**Testsakene publiseres åpent** sammen med koden, slik som dagens korpus (operatøren
|
||||
28.10). Grunnen er at brukerne selv skal kunne
|
||||
etterprøve hva som fanges og hva som er hull. Nyttelastene er inerte: bare kjente
|
||||
teknikker, `*.test`-domener og ingen fungerende kjede mot et navngitt produkt.
|
||||
|
||||
## T.4 Øktene
|
||||
|
||||
Hver økt er én leveranse, kan gis ut for seg og følger TDD med rødt før grønt.
|
||||
Nummereringen er rekkefølgen, og hver økt starter fra STATE.md.
|
||||
|
||||
**Økt 1: måling, rød før noe bygges. Ingen produktkode.**
|
||||
- Rad 1: Lag katalogregisteret som data i repoet. For hver kilde repoet viser til
|
||||
(OWASP LLM Top 10, OWASP Agentic Top 10, MITRE ATLAS, OWASP RAG Security Cheat Sheet,
|
||||
Unicode-versjonen som tegntabellene måles mot, og de andre i «Threat-model
|
||||
anchors»): utgaven som brukes, nyeste utgave, sjekkdato og kildelenke. Hver utgave
|
||||
verifiseres mot utgiveren. En kopi som er verifisert et annet sted, er et premiss
|
||||
og ikke et måleresultat.
|
||||
- Rad 2: Lag et telleskript som klassifiserer hvert sted som *gammel betydning* (kan
|
||||
mappes mekanisk, § T.5) eller *feil betydning* (krever en vurdering; for eksempel
|
||||
bruker OKF-avvisninger av YAML-former i dag `LLM10`). Frys nevneren med sha256.
|
||||
- Rad 3: Verifiser kandidatene i § T.3, legg fram grensetilfellene og frys lista.
|
||||
Skriv hver sak som test, markert som forventet rød der den ikke fanges i dag.
|
||||
- Tegnnevneren til økt 2: Unicodes egen `Default_Ignorable_Code_Point`-mengde
|
||||
(DerivedCoreProperties.txt, versjonen pinnet i registeret) pluss privat bruk-
|
||||
områdene. Det er en prinsipiell nevner i stedet for en håndplukket liste.
|
||||
|
||||
**Økt 2: usynlige tegn. Gis ut som 1.4.2 (deteksjonsatferd, ingen ny API).**
|
||||
- Hvert tegn i nevneren fanges og fjernes, eller er unntatt med en navngitt grunn
|
||||
på samme måte som ZWJ i dag: det dømmes på **kontekst**, ikke identitet. Kjente
|
||||
legitime bruk som må overleve: VS16 og VS15 etter emoji, ideografiske varianter
|
||||
(U+E0100–E01EF etter et CJK-tegn, én velger per tegn), ZWNJ i persisk og indiske
|
||||
skrifter (allerede en dokumentert rest), og LRM/RLM/ALM i høyre-til-venstre-tekst.
|
||||
En *rekke* av velgere er bærer uansett hva den står etter.
|
||||
- Både innhentingssiden og utgangskontrollen, med samme predikat på begge sider
|
||||
(som for ZWJ).
|
||||
- Vaktregelen er måling på falsk-positiv-korpuset og OKF-korpuset før og etter.
|
||||
- Etterpå sendes målingen og kontekstregelen til `llm-security-commons` som innspill
|
||||
til tegntabellen. Commons eier sin tabell, og vi skriver aldri dit.
|
||||
|
||||
**Økt 3: katalognumre med årstall (rad 2 → 0). Gis ut som 1.5.0.**
|
||||
- Alle funn bærer `LLMxx:2026`. Mapping fra 2025-betydning, verifisert i økt 1:
|
||||
LLM04 → LLM05:2026 · LLM05 → LLM10:2026 · LLM06 → LLM03:2026 ·
|
||||
LLM08 → LLM09:2026 · LLM09 → LLM07:2026 · LLM10 → LLM06:2026 ·
|
||||
LLM01 og LLM02 er uendret i betydning og får årstall.
|
||||
- Teknisk valg (kan avvises med grunn): leksikondataene holdes byte-like med
|
||||
commons, og årstallet settes på ett sted der funnet lages. Når commons publiserer
|
||||
numre med årstall, tas de inn.
|
||||
- Stedene med *feil betydning* rettes etter vurdering, hver med begrunnelse i commit.
|
||||
- Den permanente testen feiler på et katalognummer uten årstall, eller med et
|
||||
årstall som ikke er nyeste, i sporede filer utenom historikk.
|
||||
- CHANGELOG-merknaden sier rett ut at en bruker som filtrerer på `"LLM05"`, mister
|
||||
treff. Konsumentene varsles.
|
||||
|
||||
**Økt 4: katalogregisteret i bruk (rad 1). Ren dokumentasjon, gis ut med neste
|
||||
release.**
|
||||
- README-delen «What it protects against» skrives om på 2026-utgaven og kobles til
|
||||
ASI06 og relevante ATLAS-teknikker. Hver kobling verifiseres mot katalogen, og
|
||||
alt som ikke er verifisert, utelates.
|
||||
- En test feiler når registeret mangler dato eller lenke. Den feiler ikke på alder:
|
||||
automatisk varsling er utenfor retningen.
|
||||
|
||||
**Økt 5…N: angrepssakene (rad 3).** Lista fra økt 1 tas i bolker. Hver bolk blir
|
||||
enten deteksjon (TDD, vaktregelen holder) eller en dokumentert rest i LIMITATIONS og
|
||||
dekningsmatrisen (status `gap`, slik matrisen allerede gjør). Hver bolk er en minor-
|
||||
eller patch-release. Antall økter avhenger av lista og fastsettes etter økt 1.
|
||||
|
||||
**Siste økt: sluttmåling.** Rad 1–3 telles på siste release med de frosne
|
||||
nevnerne. Bare når alle tre holder, er retningen nådd.
|
||||
|
||||
## T.5 OWASP LLM Top 10: 2025 → 2026
|
||||
|
||||
Kilde: OWASPs 2026-utgave (PDF-innholdsfortegnelse, `2026/final/LLMxx_*.md` og
|
||||
README i `GenAI-Security-Project/GenAI-LLM-Top10`). Hentet fra en kopi som ble
|
||||
verifisert 02.10.2026. **Økt 1 re-verifiserer mot utgiveren før noe mappes.**
|
||||
|
||||
| 2025 | 2026 |
|
||||
|---|---|
|
||||
| LLM01 Prompt Injection | LLM01 Prompt Injection |
|
||||
| LLM02 Sensitive Information Disclosure | LLM02 Sensitive Information Disclosure |
|
||||
| LLM03 Supply Chain | LLM04 Supply Chain |
|
||||
| LLM04 Data and Model Poisoning | LLM05 Data and Model Poisoning |
|
||||
| LLM05 Improper Output Handling | LLM10 Improper Output Handling |
|
||||
| LLM06 Excessive Agency | LLM03 Excessive Agency |
|
||||
| LLM07 System Prompt Leakage | LLM08 Hidden Context Exposure |
|
||||
| LLM08 Vector and Embedding Weaknesses | LLM09 Vector and Embedding Weaknesses |
|
||||
| LLM09 Misinformation | LLM07 Misinformation |
|
||||
| LLM10 Unbounded Consumption | LLM06 Unbounded Consumption |
|
||||
|
||||
## T.6 Åpne spørsmål
|
||||
|
||||
1. ~~Publiseres testsakene åpent?~~ **Ja**, operatøren 28.10 (§ T.3).
|
||||
2. Grensetilfellene i § T.3. Legges fram i økt 1.
|
||||
|
||||
---
|
||||
|
||||
# Implementation Plan — `llm-ingestion-guard` v1
|
||||
|
||||
Derived from `docs/BRIEF.md` plus a 2026-07-04 research pass (competitive landscape,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue