fix(lexicon,docs): the script-tag row reversed — commons is now the sole diverger
llm-security commit 90f576f (2026-08-10) dropped the closing-</script>-tag requirement from hybrid-xss:script-tag, matching what the guard has always had. Both now agree in shape (no closing tag required), still not byte-identical ([^><] vs [^>]). Commons' own extracted pattern is unchanged under behaviour-preservation, so it is the only one of the three still requiring a closing tag — the opposite of what the divergence doc said when it was written. injection-lexicon.json gains source_fidelity.post_extraction_drift: the existing 83/83-at-b0de0ca claim is untouched (extraction-commit fidelity never decays), and the new 82/83-at-b1ba1fb count carries its own commit and date so it doesn't read as a bare, decaying "vs HEAD" claim. Verified directly against both upstream trees this session, not relayed: llm-security's public remote re-fetched to b1ba1fb, guard read at HEAD 0dce50f.
This commit is contained in:
parent
532d70d5ed
commit
6f79a6ea57
3 changed files with 81 additions and 3 deletions
16
CHANGELOG.md
16
CHANGELOG.md
|
|
@ -11,6 +11,22 @@ case ids, disposition semantics). Each JSON file additionally carries its own
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- `lexicon/injection-lexicon.json` (`0.5.1` → `0.6.0`) — `source_fidelity.post_extraction_drift`,
|
||||
recording that `llm-security` commit `90f576f` (2026-08-10) dropped the closing-tag
|
||||
requirement from `hybrid-xss:script-tag`'s source pattern, which this file — a frozen
|
||||
extraction under behaviour-preservation — does not follow. `patterns_byte_identical_to_source`
|
||||
(83, at extraction commit `b0de0ca`) is unchanged and still true; the new field adds the count
|
||||
against `llm-security`'s later HEAD (82/83, measured against `b1ba1fb`, 2026-08-11) so a
|
||||
consumer diffing against current upstream has a coordinate to resolve the mismatch against
|
||||
instead of finding it unexplained. No pattern text, id, or existing key changed — additive
|
||||
only, hence minor. Companion informative update in `docs/lexicon-port-divergence.md`, whose
|
||||
`hybrid-xss:script-tag` row is reversed: commons is now the sole diverger of the three runtimes
|
||||
on this one construct, not the guard.
|
||||
|
||||
Repository tag unaffected — no file set, key name, case id, or disposition semantics moved.
|
||||
|
||||
## [0.2.0] — 2026-08-11
|
||||
|
||||
The contract gained a normative MUST, which is why this is a release rather than a
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ Divergence is **not one-directional**. Each side has inputs the other's pattern
|
|||
| `markdown: injection payload in link anchor text` | **guard misses** | `[click ignore this](http://e.com/a(b))` |
|
||||
| `sub-agent: spawn instruction with dangerous capability keywords` | **guard misses** | `create an agent that` + 20 filler words + `execute` |
|
||||
| `sub-agent: delegation with safety bypass instruction` | **guard misses** | `delegate to a new agent` + 200 chars + `bypass` |
|
||||
| `hybrid-xss: <script> tag in content (agent context XSS)` | **commons misses**; span differs | `<script>alert(1)` (unclosed), `<script src=x.js>` |
|
||||
| `hybrid-xss: <script> tag in content (agent context XSS)` | **reversed 2026-08-11, see below** | `<script>alert(1)` (unclosed), `<script src=x.js>` |
|
||||
| `hybrid-xss: iframe with executable src (agent context XSS)` | **guard misses the label, not the attack** | `<iframe data-x="<" src="javascript:alert(1)">` |
|
||||
|
||||
The last row is the one of the 13 that does not reach report level. The guard's
|
||||
|
|
@ -109,6 +109,48 @@ consumer reports offsets or evidence text; it does not change whether a finding
|
|||
The commons-side misses were confirmed in a real JS engine (Node v25.8.2, `RegExp` built from
|
||||
the committed JSON), not only in the Python harness used for the differential.
|
||||
|
||||
### `hybrid-xss:script-tag`: the row reversed, 2026-08-11
|
||||
|
||||
At the time this file was written, `<script>alert(1)` (unclosed) and `<script src=x.js>` were
|
||||
commons misses only in the sense that commons was a byte-identical extraction of
|
||||
`llm-security`, so "commons misses" meant "commons and `llm-security` both miss, the guard
|
||||
does not." That symmetry broke on `llm-security`'s side.
|
||||
|
||||
`llm-security` commit `90f576f` (`fix(llm-security): v8.x-A - close <script> recall hole, add
|
||||
whole-table ReDoS gate`) replaced the source pattern
|
||||
|
||||
```
|
||||
<script\b[^>]*>[\s\S]*?<\/script>
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```
|
||||
<script\b[^>]*>
|
||||
```
|
||||
|
||||
dropping the closing-tag requirement that produced the recall hole this file first measured.
|
||||
Both witnesses now match on `llm-security`'s side. Verified directly against the module at
|
||||
commit `c67bad3` (2026-08-10, first commit carrying the change) and re-confirmed unmoved at
|
||||
`b1ba1fb` (2026-08-11, current public-remote HEAD as fetched this session) — `git diff
|
||||
c67bad3..b1ba1fb -- scanners/lib/injection-patterns.mjs` is empty, so no later commit touched
|
||||
the pattern a second time.
|
||||
|
||||
The guard's pattern was never the same construct: `<script\b[^><]*>`, negated-class excluding
|
||||
both `>` and `<` (`src/llm_ingestion_guard/injection_lexicon.json:463`, unchanged since
|
||||
`de09711`, re-confirmed unmoved through current guard HEAD `0dce50f`, 2026-08-11). The two
|
||||
patterns now agree on **shape** — both drop the closing-tag requirement, both are a single
|
||||
negated-class run immediately after `<script\b` — but they are still not byte-identical: the
|
||||
guard's excluded-character class also excludes `<`, `llm-security`'s does not. That one-byte
|
||||
difference is unresolved on both sides (see *Open questions* in the coordination thread); it
|
||||
does not reopen the closing-tag question, which is settled.
|
||||
|
||||
Commons still carries the pre-`90f576f` form, unchanged, per this repository's
|
||||
behaviour-preservation invariant — commons does not follow either upstream regex change
|
||||
without an operator decision to re-extract. **Commons is now the sole diverger of the three**
|
||||
on the closing-tag requirement: both `llm-security` and the guard match `<script src=x.js>`
|
||||
and unclosed `<script>alert(1)`; commons' extracted pattern still requires `</script>`.
|
||||
|
||||
## Why they diverge: two different ReDoS mitigations of one table
|
||||
|
||||
This is not drift, and framing it as a bug in either repository would be wrong.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "0.5.1",
|
||||
"version": "0.6.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",
|
||||
|
|
@ -112,7 +112,27 @@
|
|||
"why_retracted": "The same transcription inversion in the opposite direction. The module writes pr[e\\u00e9]c[e\\u00e9]dentes? with escapes; this was the only one of the 83 patterns not byte-identical to source. Corrected in 0.4.0 to the module's spelling, which makes the count 83/83.",
|
||||
"behaviour_impact": "None. The two spellings are the same regular expression. Verified by compiling both forms and comparing match presence and offsets in Node (bare and `u` mode) and in Python `re` over accented, unaccented, uppercase and non-matching French inputs - identical results throughout."
|
||||
}
|
||||
]
|
||||
],
|
||||
"post_extraction_drift": {
|
||||
"$comment": "patterns_byte_identical_to_source above states fidelity AT the commit this file was extracted from (b0de0ca) and does not update when llm-security's source moves further - that is what behaviour-preservation means. Recorded here because llm-security has since moved on one pattern, and a consumer diffing this file against llm-security's current source would otherwise find an unexplained mismatch with no coordinate to resolve it against. See docs/lexicon-port-divergence.md for the full account.",
|
||||
"extracted_from_commit": "b0de0ca",
|
||||
"extracted_from_commit_date": "2026-08-09",
|
||||
"count_at_extraction": 83,
|
||||
"drift": [
|
||||
{
|
||||
"pattern_id": "hybrid-xss:script-tag",
|
||||
"source_commit": "90f576f",
|
||||
"source_commit_date": "2026-08-10",
|
||||
"change": "llm-security dropped the closing-tag requirement: <script\\b[^>]*>[\\s\\S]*?<\\/script> became <script\\b[^>]*>, closing a recall hole where `<script>alert(1)` (unclosed) and `<script src=x.js>` produced no finding.",
|
||||
"commons_pattern_unchanged": true,
|
||||
"reconfirmed_no_further_drift_at": "b1ba1fb",
|
||||
"reconfirmed_date": "2026-08-11",
|
||||
"reconfirmed_method": "git diff 90f576f..b1ba1fb -- scanners/lib/injection-patterns.mjs on a fresh fetch of the public remote is empty for this pattern; no later commit touched it a second time."
|
||||
}
|
||||
],
|
||||
"count_against_llm_security_head_as_of_2026_08_11": 82,
|
||||
"count_against_llm_security_head_note": "b1ba1fb was llm-security's public-remote HEAD when this was measured, 2026-08-11. Not re-checked automatically; re-verify before citing against a later HEAD."
|
||||
}
|
||||
},
|
||||
"families": [
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue