feat(lexicon): add injection-lexicon.json from verified llm-security dump
The four prompt-injection pattern families — 21 critical, 32 high, 22 medium, 8 hybrid — with per-pattern label, ECMAScript source and declared flags. Data only. The dump names checkCognitiveLoadTrap and scanForInjection's variant building (normalise → fold → rot13 → unicode-tag escalation) as ENGINE logic that never moves here; they are absent by intent, not omission. Proven, not transcribed: all four arrays were rebuilt from the commons JSON alone and diffed against the imported dump module — 83/83 identical on label, source and flags, 81 of them byte-identical. All 83 compile in Node bare, Node under `u`, and Python `re`. Two deliberate deviations from byte-identity, declared in the file: the zero-width and Cyrillic character classes carried raw code points, four of them invisible. Escaped to \uXXXX (the convention forbids raw invisible code points outside conformance inputs — an unreviewable class is where a silent false negative hides) and proven equivalent by differential match-set comparison over 208 adversarial inputs, 832 comparisons, 0 differences. Class membership was counted from the dump bytes: the zero-width class holds 4 code points and does NOT include U+00AD. HYBRID_PATTERNS' severity was not supplied and is left null rather than inferred from its siblings. Verification log in docs/extraction-plan.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FaYqid3mejFmd9ZHsiHgp3
This commit is contained in:
parent
0433240b14
commit
23cf3e383a
2 changed files with 552 additions and 0 deletions
|
|
@ -111,6 +111,28 @@ the property list is a lower bound; `scanner` and `severity` are required by des
|
||||||
than by evidence; and the JSONL profile is left explicitly `unspecified` rather than
|
than by evidence; and the JSONL profile is left explicitly `unspecified` rather than
|
||||||
invented, because "one finding per line" is inference.
|
invented, because "one finding per line" is inference.
|
||||||
|
|
||||||
|
### `lexicon/injection-lexicon.json` — extracted 2026-08-09
|
||||||
|
|
||||||
|
Source: `llm-security/scanners/lib/injection-patterns.mjs`, supplied as operator dump 2/2
|
||||||
|
through the local coord mailbox. No commit hash accompanied it, so provenance is recorded
|
||||||
|
as `unknown` rather than guessed.
|
||||||
|
|
||||||
|
| Check | Method | Result |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| JSON well-formed, `version` present, LF, trailing newline, no raw invisible code points | `python3 -m json.tool` + a byte scan for U+200B/200C/200D/FEFF/00AD and the Tag block | pass, 0 raw invisible code points |
|
||||||
|
| Pattern text and flags reproduce the source | rebuilt all four arrays **from the commons JSON alone** (`new RegExp(p.pattern, p.flags ?? '')`) and diffed label, `.source` and `.flags` against the imported dump module | 83/83 compared, 0 differences; 81/83 byte-identical, 2 declared-normalised |
|
||||||
|
| Flags were read mechanically, not by eye | extracted from each literal via `.flags` | critical 15×`i` / 3×`m` / 3 none, high 32×`i`, medium 20×`i` / 2 none, hybrid 8×`i` |
|
||||||
|
| Every pattern compiles in both runtimes | `new RegExp(src, flags)` and again with `u` in Node; `re.compile` with the equivalent `re.I`/`re.M` in Python | 83/83 in all three modes, 0 failures |
|
||||||
|
| The 2 normalised patterns behave identically | differential match-set comparison (offsets + matched text) against the source objects, bare and under `u`, over a 208-input adversarial corpus: every class member, the near-misses excluded from each class (U+00AD, U+2060, U+180E, Cyrillic х, the uppercase set, Greek look-alikes), run boundaries, repeats, empty input | 832 comparisons, 0 differences |
|
||||||
|
| Class membership was counted, not assumed | enumerated the code points inside each character class directly from the dump bytes | zero-width class = 4 (U+200B, U+200C, U+200D, U+FEFF — **not** U+00AD); Cyrillic class = 7 (U+0430, U+0435, U+043E, U+0440, U+0441, U+0456, U+0443) |
|
||||||
|
| `\/` is portable, not a defect | 9 patterns carry the redundant escape a JS regex literal requires; compiled in Node bare, Node `u`, and Python `re` | accepted by all three — kept byte-identical, recorded as a translation note for engines that reject unknown escapes |
|
||||||
|
|
||||||
|
Not verified, and not claimed: that the dump matches the module it was transcribed from.
|
||||||
|
Every check above proves this JSON agrees with **the dump**; dump-to-module fidelity is
|
||||||
|
`llm-security`'s assertion, reproducible only in a session with read access to that
|
||||||
|
repository. The severity the engine assigns to `HYBRID_PATTERNS` was not supplied and is
|
||||||
|
left `null` rather than inferred from its three sibling arrays.
|
||||||
|
|
||||||
## Definition of done for v0.1.0
|
## Definition of done for v0.1.0
|
||||||
|
|
||||||
1. Repository initialized, Forgejo remote `open/llm-security-commons`, MIT, `STATE.md`
|
1. Repository initialized, Forgejo remote `open/llm-security-commons`, MIT, `STATE.md`
|
||||||
|
|
|
||||||
530
lexicon/injection-lexicon.json
Normal file
530
lexicon/injection-lexicon.json
Normal file
|
|
@ -0,0 +1,530 @@
|
||||||
|
{
|
||||||
|
"version": "0.1.0",
|
||||||
|
"id": "injection-lexicon",
|
||||||
|
"description": "Prompt-injection pattern lexicon: the four pattern families a detector matches against untrusted text, and the severity family each belongs to. Data only. The variant building that feeds these patterns (normalisation, homoglyph folding, rot13, unicode-tag escalation) and the buried-payload heuristic are engine behaviour and are deliberately NOT described here.",
|
||||||
|
"owasp": "LLM01",
|
||||||
|
"label_format": "{class}: {detail}",
|
||||||
|
"$comment": "Extracted without behaviour change from llm-security/scanners/lib/injection-patterns.mjs, delivered as operator dump 2/2 through the local coord mailbox on 2026-08-09. Only the four pattern arrays are data. The dump states explicitly that checkCognitiveLoadTrap (the buried-after-2000-chars logic) and scanForInjection's variant building are ENGINE logic that never moves here; they are absent by intent, not by omission. Array order is preserved exactly as delivered.",
|
||||||
|
"provenance": {
|
||||||
|
"source_repo": "llm-security",
|
||||||
|
"source_files": [
|
||||||
|
"scanners/lib/injection-patterns.mjs"
|
||||||
|
],
|
||||||
|
"source_exports": [
|
||||||
|
"CRITICAL_PATTERNS",
|
||||||
|
"HIGH_PATTERNS",
|
||||||
|
"MEDIUM_PATTERNS",
|
||||||
|
"HYBRID_PATTERNS"
|
||||||
|
],
|
||||||
|
"source_delivery": "operator dump 2/2, coord message from llm-security, 2026-08-09",
|
||||||
|
"source_commit": "unknown - not supplied with the dump",
|
||||||
|
"verified": "differentially, against the dump",
|
||||||
|
"evidence_limits": [
|
||||||
|
"The dump is a transcription of the source module, not the module file itself. Every check recorded for this file therefore proves that this JSON agrees with the DUMP. That the dump agrees with the module is llm-security's assertion, and is not a result reproduced here.",
|
||||||
|
"The severity the engine assigns to the hybrid family was not supplied. See families[].severity_note.",
|
||||||
|
"Whether a consumer applies these patterns to raw or to normalised text is engine behaviour and is not fixed by this file. Two runtimes matching identical patterns against differently normalised text will still disagree on identical input."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dialect": {
|
||||||
|
"name": "ecmascript",
|
||||||
|
"$comment": "Patterns are ECMAScript regular-expression source text, exactly as the source literals spell it. Flags are declared per pattern in a `flags` field and never inlined as `(?i)` or `(?m)`; a pattern with no `flags` key carries no flags. All 83 patterns compile in Node with their declared flags, in Node with `u` added, and in Python `re` with the equivalent re.I / re.M.",
|
||||||
|
"flags": {
|
||||||
|
"i": "case-insensitive",
|
||||||
|
"m": "multiline: ^ and $ match at line boundaries"
|
||||||
|
},
|
||||||
|
"features_used": [
|
||||||
|
"negative lookahead: (?!...)",
|
||||||
|
"lookahead assertion: (?=...)",
|
||||||
|
"non-capturing groups: (?:...)",
|
||||||
|
"bounded quantifiers: {n,m}",
|
||||||
|
"unicode escapes: \\uXXXX"
|
||||||
|
],
|
||||||
|
"translation_notes": [
|
||||||
|
"Python (`re`): compile with re.I where flags contain `i` and re.M where they contain `m`. No rewriting is needed; verified by compiling all 83.",
|
||||||
|
"Nine patterns contain `\\/` - a redundant escape that a JavaScript regex LITERAL requires and that `RegExp.prototype.source` preserves. It is kept rather than normalised away because both seed runtimes accept it (Node bare, Node under `u`, and Python `re`), so removing it would break byte-identity to buy nothing. Engines that reject unknown escapes (Go `regexp`, RE2) MUST report these patterns as unsupported rather than skip them silently - a skipped pattern is an invisible false negative.",
|
||||||
|
"`\\w` and `\\b` are ASCII-only in ECMAScript without `u` but Unicode-aware in Python on `str`. Input that mixes non-ASCII word characters with these patterns can therefore match differently between runtimes. This is a real portability seam. It is recorded rather than normalised, because normalising it would change behaviour in the seed runtime.",
|
||||||
|
"The leetspeak and multi-language patterns embed non-ASCII literals (accented Latin) directly. Those are visible characters and are left exactly as written."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"normalisations": [
|
||||||
|
{
|
||||||
|
"id": "unicode-escape-invisible-and-confusable",
|
||||||
|
"affects": [
|
||||||
|
"homoglyph: Cyrillic-Latin mixing in adjacent characters",
|
||||||
|
"unicode: zero-width character inside word (keyword splitting)"
|
||||||
|
],
|
||||||
|
"from": "literal U+200B U+200C U+200D U+FEFF, and literal Cyrillic a/e/o/r/s/i/u, inside character classes",
|
||||||
|
"to": "the same code points written as \\uXXXX escapes",
|
||||||
|
"reason": "The source literals carry these code points RAW. Four of them are invisible and seven are Latin look-alikes, so in that form the pattern text cannot be reviewed, diffed or copied safely: a reviewer cannot see whether a class holds four code points or five. This repository's convention forbids raw invisible code points outside conformance inputs for exactly this reason. The escaped spelling is the same regular expression to both engines.",
|
||||||
|
"equivalence_evidence": "Differential match-set comparison (match offsets and matched text) between the raw and the escaped form: Node over 173 adversarial inputs in both bare and `u` mode (692 comparisons), and Python `re` over 118 inputs (236 comparisons). Zero differences. The corpus covers every member of each class, the near-misses deliberately excluded from it (U+00AD, U+2060, U+180E, Cyrillic x, the Cyrillic uppercase set, Greek look-alikes), run boundaries, repeats, and empty input.",
|
||||||
|
"class_membership_verified": {
|
||||||
|
"zero_width_class": [
|
||||||
|
"U+200B",
|
||||||
|
"U+200C",
|
||||||
|
"U+200D",
|
||||||
|
"U+FEFF"
|
||||||
|
],
|
||||||
|
"cyrillic_class": [
|
||||||
|
"U+0430",
|
||||||
|
"U+0435",
|
||||||
|
"U+043E",
|
||||||
|
"U+0440",
|
||||||
|
"U+0441",
|
||||||
|
"U+0456",
|
||||||
|
"U+0443"
|
||||||
|
],
|
||||||
|
"$comment": "Enumerated mechanically from the dump bytes, not by eye. Note that the zero-width class here does NOT include U+00AD even though codepoints/carriers.json lists U+00AD as a zero-width carrier, and that the Cyrillic class here is a 7-member set distinct from the 13-member CYRILLIC_CONFUSABLES list in that same file. The three sets are deliberately different in the seed implementation and are NOT reconciled here."
|
||||||
|
},
|
||||||
|
"byte_identical_to_source": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"families": [
|
||||||
|
{
|
||||||
|
"id": "critical",
|
||||||
|
"source_export": "CRITICAL_PATTERNS",
|
||||||
|
"severity": "critical",
|
||||||
|
"count": 21,
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"label": "override: ignore previous instructions",
|
||||||
|
"pattern": "ignore\\s+(?:all\\s+)?previous",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "override: forget instructions",
|
||||||
|
"pattern": "forget\\s+your\\s+(?:instructions|rules|guidelines|directives)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "override: disregard instructions",
|
||||||
|
"pattern": "disregard\\s+your",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "override: override instructions",
|
||||||
|
"pattern": "override\\s+your",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "override: suspend constraints",
|
||||||
|
"pattern": "suspend\\s+all\\s+constraints",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "override: prior constraints",
|
||||||
|
"pattern": "all\\s+prior\\s+constraints",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "spoofed header: # SYSTEM:",
|
||||||
|
"pattern": "^#+\\s*SYSTEM\\s*:",
|
||||||
|
"flags": "m"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "spoofed header: [INST]",
|
||||||
|
"pattern": "^\\[INST\\]",
|
||||||
|
"flags": "m"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "spoofed header: <|system|>",
|
||||||
|
"pattern": "<\\|system\\|>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "spoofed tag: <system>",
|
||||||
|
"pattern": "<system>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "spoofed tag: </system>",
|
||||||
|
"pattern": "<\\/system>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "spoofed header: ### Instructions:",
|
||||||
|
"pattern": "^###\\s*Instructions\\s*:",
|
||||||
|
"flags": "m"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "identity: you are no longer",
|
||||||
|
"pattern": "you\\s+are\\s+no\\s+longer",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "identity: you are now [name]",
|
||||||
|
"pattern": "you\\s+are\\s+now\\s+(?!able|going|ready|done|running|using|looking|in\\s|at\\s|on\\s)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "identity: your new role",
|
||||||
|
"pattern": "your\\s+new\\s+role\\s+is",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "identity: new primary directive",
|
||||||
|
"pattern": "your\\s+new\\s+primary\\s+directive",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "identity: pretend you are",
|
||||||
|
"pattern": "pretend\\s+you\\s+are",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "config: ignore CLAUDE.md",
|
||||||
|
"pattern": "ignore\\s+your\\s+CLAUDE\\.md",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "config: override system prompt",
|
||||||
|
"pattern": "override\\s+your\\s+system\\s+prompt",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "config: bypass safety",
|
||||||
|
"pattern": "bypass\\s+your\\s+safety",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "config: disable output filtering",
|
||||||
|
"pattern": "disable\\s+output\\s+filtering",
|
||||||
|
"flags": "i"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "high",
|
||||||
|
"source_export": "HIGH_PATTERNS",
|
||||||
|
"severity": "high",
|
||||||
|
"count": 32,
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"label": "normalization: prioritize user over rules",
|
||||||
|
"pattern": "always\\s+prioritize\\s+user\\s+requests?\\s+over",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "normalization: user intent precedence",
|
||||||
|
"pattern": "user\\s+intent\\s+takes?\\s+precedence\\s+over",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "normalization: CLAUDE.md conflict override",
|
||||||
|
"pattern": "if\\s+CLAUDE\\.md\\s+conflicts",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "normalization: skip confirmation",
|
||||||
|
"pattern": "skip\\s+confirmation\\s+for",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "reframing: your actual task",
|
||||||
|
"pattern": "your\\s+actual\\s+task\\s+is",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "reframing: your real purpose",
|
||||||
|
"pattern": "your\\s+real\\s+purpose\\s+is",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "reframing: what you should actually do",
|
||||||
|
"pattern": "what\\s+you\\s+should\\s+actually\\s+do",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hidden comment: agent-directed HTML comment",
|
||||||
|
"pattern": "<!--\\s*(?:AGENT|AI|HIDDEN|ACTUAL\\s+TASK|REAL\\s+INSTRUCTION)\\s*:",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "html-obfuscation: display:none element with content",
|
||||||
|
"pattern": "<[^>]{1,256}style\\s*=\\s*\"[^\"]{0,256}display\\s*:\\s*none[^\"]{0,256}\"[^>]{0,256}>",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "html-obfuscation: visibility:hidden element",
|
||||||
|
"pattern": "<[^>]{1,256}style\\s*=\\s*\"[^\"]{0,256}visibility\\s*:\\s*hidden[^\"]{0,256}\"[^>]{0,256}>",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "html-obfuscation: off-screen positioned element",
|
||||||
|
"pattern": "<[^>]{1,256}style\\s*=\\s*\"[^\"]{0,256}position\\s*:\\s*absolute[^\"]{0,256}-\\d{3,}px[^\"]{0,256}\"[^>]{0,256}>",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "html-obfuscation: zero font-size element",
|
||||||
|
"pattern": "<[^>]{1,256}style\\s*=\\s*\"[^\"]{0,256}font-size\\s*:\\s*0[^\"]{0,256}\"[^>]{0,256}>",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "html-obfuscation: zero opacity element",
|
||||||
|
"pattern": "<[^>]{1,256}style\\s*=\\s*\"[^\"]{0,256}opacity\\s*:\\s*0[^\"]{0,256}\"[^>]{0,256}>",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "html-obfuscation: zero-size overflow-hidden element",
|
||||||
|
"pattern": "<[^>]{1,256}style\\s*=\\s*\"[^\"]{0,256}(?:height|width)\\s*:\\s*0[^\"]{0,256}overflow\\s*:\\s*hidden[^\"]{0,256}\"[^>]{0,256}>",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "html-obfuscation: injection in aria-label attribute",
|
||||||
|
"pattern": "aria-label\\s*=\\s*\"[^\"]{0,256}(?:ignore|override|system|instruction|execute|exfiltrate)[^\"]{0,256}\"",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "evasion: educational purpose framing",
|
||||||
|
"pattern": "for\\s+educational\\s+purposes?\\s+only",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "evasion: hypothetical scenario framing",
|
||||||
|
"pattern": "(?:this\\s+is\\s+)?a\\s+hypothetical\\s+scenario",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "evasion: fictional setting framing",
|
||||||
|
"pattern": "in\\s+a\\s+fictional\\s+(?:setting|scenario|world)\\s+where",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "evasion: red-team exercise framing",
|
||||||
|
"pattern": "(?:this\\s+is\\s+)?a\\s+red[- ]?team(?:ing)?\\s+(?:exercise|simulation|test)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "evasion: security audit simulation framing",
|
||||||
|
"pattern": "security\\s+audit\\s+simulation",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "evasion: test/lab/sandbox pretense",
|
||||||
|
"pattern": "pretend\\s+(?:this\\s+is|we\\s+are\\s+in)\\s+a\\s+(?:test|lab|sandbox|simulation)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "evasion: thought experiment framing",
|
||||||
|
"pattern": "as\\s+a\\s+thought\\s+experiment",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "evasion: research purpose framing",
|
||||||
|
"pattern": "for\\s+(?:research|academic|scientific)\\s+purposes",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "evasion: academic context framing",
|
||||||
|
"pattern": "in\\s+an?\\s+(?:academic|research|educational)\\s+context",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hitl-trap: approval urgency — approve immediately",
|
||||||
|
"pattern": "(?:approve|accept|confirm)\\s+(?:this\\s+)?immediately",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hitl-trap: approval urgency — no need to review",
|
||||||
|
"pattern": "no\\s+need\\s+to\\s+review",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hitl-trap: approval urgency — just approve",
|
||||||
|
"pattern": "(?:just|simply)\\s+(?:approve|accept|confirm)\\s+(?:it|this|everything)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hitl-trap: approval urgency — suppress review",
|
||||||
|
"pattern": "(?:don'?t|do\\s+not)\\s+(?:bother\\s+)?(?:check|review|verify|inspect|read)(?:ing)?\\s+(?:this|the|it)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hitl-trap: summary suppression — for brevity, skipping",
|
||||||
|
"pattern": "for\\s+brevity[\\s,]+(?:skipping|omitting|leaving\\s+out)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hitl-trap: summary suppression — too long to show",
|
||||||
|
"pattern": "(?:too\\s+(?:long|verbose|detailed)\\s+to\\s+(?:show|display|list|include))",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hitl-trap: summary suppression — details omitted",
|
||||||
|
"pattern": "(?:details?\\s+(?:omitted|redacted|hidden|suppressed))",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hitl-trap: scope minimization — minor change + destructive action",
|
||||||
|
"pattern": "(?:minor|trivial|small|cosmetic)\\s+(?:change|update|fix|adjustment)\\b[^.]{0,80}(?:delet|remov|drop|truncat|reset|destroy|\\bformat\\b|wipe)",
|
||||||
|
"flags": "i"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "medium",
|
||||||
|
"source_export": "MEDIUM_PATTERNS",
|
||||||
|
"severity": "medium",
|
||||||
|
"count": 22,
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"label": "leetspeak: ignore previous (obfuscated)",
|
||||||
|
"pattern": "[1!|l][gq9]n[o0]r[e3]\\s+(?:all\\s+)?pr[e3]v[i1!|l][o0]us",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "leetspeak: forget instructions (obfuscated)",
|
||||||
|
"pattern": "f[o0]rg[e3]t\\s+y[o0]ur\\s+[i1!|l]nstruct[i1!|l][o0]ns",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "leetspeak: disregard your (obfuscated)",
|
||||||
|
"pattern": "d[i1!|l]sr[e3]g[a4@]rd\\s+y[o0]ur",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "leetspeak: override your (obfuscated)",
|
||||||
|
"pattern": "[o0]v[e3]rr[i1!|l]d[e3]\\s+y[o0]ur",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "homoglyph: Cyrillic-Latin mixing in adjacent characters",
|
||||||
|
"pattern": "[a-zA-Z][\\u0430\\u0435\\u043E\\u0440\\u0441\\u0456\\u0443]|[\\u0430\\u0435\\u043E\\u0440\\u0441\\u0456\\u0443][a-zA-Z]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "unicode: zero-width character inside word (keyword splitting)",
|
||||||
|
"pattern": "\\w[\\u200B\\u200C\\u200D\\uFEFF]\\w"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "indirect: instruction addressed to AI/assistant",
|
||||||
|
"pattern": "(?:note|message|instruction)\\s+(?:to|for)\\s+(?:the\\s+)?(?:AI|assistant|model|LLM|Claude)\\b",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "indirect: direct address to AI/assistant",
|
||||||
|
"pattern": "(?:dear|attention)\\s+(?:AI|assistant|model|LLM|Claude)\\b",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "indirect: trigger-based instruction for AI",
|
||||||
|
"pattern": "when\\s+(?:you|the\\s+AI|the\\s+assistant|Claude)\\s+(?:read|see|encounter|process)\\s+this",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "multi-lang: French \"ignore previous instructions\"",
|
||||||
|
"pattern": "ignor(?:ez?|er?)\\s+(?:les?\\s+)?instructions?\\s+pr[eé]c[eé]dentes?",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "multi-lang: Spanish \"ignore previous instructions\"",
|
||||||
|
"pattern": "ignor(?:ar?|e)\\s+(?:las?\\s+)?instrucciones?\\s+anteriores?",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "multi-lang: German \"ignore previous instructions\"",
|
||||||
|
"pattern": "ignorier(?:e|en)?\\s+(?:alle\\s+)?vorherigen?\\s+(?:Anweisungen|Instruktionen)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "markdown: suspicious instruction in link-reference comment",
|
||||||
|
"pattern": "\\[\\/\\/\\]:\\s*#\\s*\\(.*(?:ignore|override|system|instruction|execute)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "data-uri: executable content type",
|
||||||
|
"pattern": "data:(?:text\\/html|application\\/javascript|text\\/javascript)[;,]",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "markdown: injection payload in link anchor text",
|
||||||
|
"pattern": "\\[[^\\]]*(?:system|ignore|override|exfiltrate|execute)[^\\]]*\\]\\([^)]+\\)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "sub-agent: spawn instruction with dangerous capability keywords",
|
||||||
|
"pattern": "(?:create|spawn|launch|start|run)\\s+(?:an?\\s+)?(?:new\\s+)?(?:sub-?agent|agent|task|worker)\\s+(?:that|to|which|with)\\s+(?:.*?\\s+)?(?:execute|run|delete|remove|send|post|exfiltrate|access|reads?\\s+(?:.*?\\s+)?(?:secret|credential|key|token|\\.env|\\.ssh))",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "sub-agent: delegation with safety bypass instruction",
|
||||||
|
"pattern": "(?:delegate|dispatch)\\s+(?:to\\s+)?(?:an?\\s+)?(?:new\\s+)?(?:agent|sub-?agent|task)\\s+.*?(?:bypass|override|ignore|without\\s+(?:review|confirmation|approval))",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "nl-indirection: fetch URL and execute",
|
||||||
|
"pattern": "fetch\\s+(?:this|the|that)\\s+(?:URL|link|endpoint)\\s+and\\s+(?:execute|run|eval)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "nl-indirection: send data to external destination",
|
||||||
|
"pattern": "send\\s+(?:this|the|that|all)\\s+(?:data|content|output|result|information|file)\\s+to\\s+(?:https?:\\/\\/|ftp:\\/\\/|\\S+@\\S+)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "nl-indirection: read sensitive dotfile path",
|
||||||
|
"pattern": "read\\s+(?:the\\s+)?(?:contents?\\s+of\\s+)?(?:~\\/)?\\.(?:ssh|aws|gnupg|env)\\b",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "nl-indirection: extract credentials and exfiltrate",
|
||||||
|
"pattern": "(?:extract|copy|dump|exfiltrate)\\s+(?:all\\s+)?(?:the\\s+)?(?:credentials?|secrets?|tokens?|keys?|passwords?)\\s+(?:and|then)\\s+(?:send|post|upload|transmit)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "nl-indirection: download and execute",
|
||||||
|
"pattern": "(?:download|fetch|retrieve)\\s+(?:from\\s+)?\\S+\\s+(?:and|then)\\s+(?:execute|run|eval|pipe\\s+to\\s+(?:bash|sh|node|python))",
|
||||||
|
"flags": "i"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hybrid",
|
||||||
|
"source_export": "HYBRID_PATTERNS",
|
||||||
|
"severity": null,
|
||||||
|
"severity_note": "The seed dump supplies this array but NOT the severity the engine assigns to it. Left null rather than inferred from the three sibling arrays. A consumer MUST NOT assume a severity for this family until the producing module is published.",
|
||||||
|
"count": 8,
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"label": "hybrid-p2sql: injection + SQL keywords (prompt-to-SQL attack)",
|
||||||
|
"pattern": "(?:ignore|override|disregard|forget)[^.]{0,60}(?:SELECT\\s+\\*|DROP\\s+TABLE|UNION\\s+SELECT|DELETE\\s+FROM|INSERT\\s+INTO|UPDATE\\s+\\w+\\s+SET)(?:\\b|(?=\\s|$))",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hybrid-p2sql: SQL operation + injection override keywords",
|
||||||
|
"pattern": "(?:SELECT\\s+\\*|DROP\\s+TABLE|UNION\\s+SELECT|DELETE\\s+FROM)\\s[^;]{0,80}(?:ignore|override|disregard|bypass)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hybrid-recursive: instruction to inject into model output",
|
||||||
|
"pattern": "(?:inject|insert|embed|include)\\s+(?:this|the\\s+following)\\s+(?:into|in)\\s+(?:your|the)\\s+(?:output|response|reply|message|prompt|context)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hybrid-recursive: conditional response injection (recursive payload)",
|
||||||
|
"pattern": "(?:when|if)\\s+(?:the\\s+)?(?:user|human|operator)\\s+(?:asks?|requests?|queries)[^.]{0,60}(?:respond\\s+with|output|reply\\s+with|include)\\s+(?:this|the\\s+following)",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hybrid-xss: <script> tag in content (agent context XSS)",
|
||||||
|
"pattern": "<script\\b[^>]*>[\\s\\S]*?<\\/script>",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hybrid-xss: javascript: URI scheme (agent context XSS)",
|
||||||
|
"pattern": "javascript\\s*:",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hybrid-xss: inline event handler attribute (agent context XSS)",
|
||||||
|
"pattern": "\\bon(?:error|load|click|mouseover|focus|blur)\\s*=",
|
||||||
|
"flags": "i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "hybrid-xss: iframe with executable src (agent context XSS)",
|
||||||
|
"pattern": "<iframe\\b[^>]*src\\s*=\\s*[\"'][^\"']*(?:javascript:|data:text\\/html)",
|
||||||
|
"flags": "i"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"totals": {
|
||||||
|
"families": 4,
|
||||||
|
"patterns": 83
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue