docs(divergence): the span row had one witness; llm-security measured five more
Their coord message of 2026-08-11T11:01:59Z measured the three <script> forms as totally ordered by what they match — [^>] strictly contains [^><] strictly contains the pre-0.7.0 closing-tag form — and named two input classes the guard's narrower class drops that commons had not recorded: `<script a="<" >x` and `<script<div>`. Reproduced independently before writing it down, including the strict-superset property in both directions. Their table came with a claim attached; the claim is now a measurement here rather than a relayed assertion. Their argument for [^>] — the narrower class buys an empty false-positive surface, since anything reaching [^>]-and-not-[^><] already contains a literal <script tag — is recorded as THEIRS and marked explicitly as not what decided commons' form. Commons carries [^>] on provenance and would have carried [^><] had the source been the guard's. Keeping that distinction visible matters more than the regex: if merit ever becomes the reason a commons pattern moves, behaviour-preservation is gone. Also records honestly that they asked to hear the guard's reason for [^><] before commons shipped, and commons shipped first — with why that order is defensible rather than an oversight. A reason that beats their argument is a reason for the guard's own port; commons would still track its declared source. Informative file only. v0.3.0 unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HuudQLGMyMenuyeZk8fKs5
This commit is contained in:
parent
4641a7b518
commit
d96fbbf791
2 changed files with 47 additions and 12 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
|
@ -11,7 +11,23 @@ case ids, disposition semantics). Each JSON file additionally carries its own
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
Nothing yet.
|
### Changed
|
||||||
|
|
||||||
|
- `docs/lexicon-port-divergence.md` (informative) — the residual `[^>]` vs `[^><]` row gains a
|
||||||
|
fuller witness set. `llm-security` measured the three forms as **totally ordered** by what they
|
||||||
|
match, each a strict superset of the next, and named two input classes the guard's narrower
|
||||||
|
class drops (`<script a="<" >x`, `<script<div>`) beyond the one commons had recorded.
|
||||||
|
Reproduced here independently, including the strict-superset property in both directions,
|
||||||
|
before being written down.
|
||||||
|
|
||||||
|
Their argument — that the narrower class buys an empty false-positive surface, since anything
|
||||||
|
reaching `[^>]`-and-not-`[^><]` already contains a literal `<script` tag — is recorded as
|
||||||
|
theirs and explicitly **not** what decided commons' form. Commons carries `[^>]` on provenance,
|
||||||
|
and would have carried `[^><]` had the source been the guard's. Also records that they asked to
|
||||||
|
hear the guard's reason for `[^><]` before commons shipped and commons shipped first, with why
|
||||||
|
that order was deliberate.
|
||||||
|
|
||||||
|
No data file touched; `v0.3.0` is unaffected.
|
||||||
|
|
||||||
## [0.3.0] — 2026-08-11
|
## [0.3.0] — 2026-08-11
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -167,17 +167,36 @@ one, so relative to `0.6.0` it can add matches and cannot add a false negative.
|
||||||
would not have been adoptable on the same reasoning.
|
would not have been adoptable on the same reasoning.
|
||||||
|
|
||||||
**What is still open is the one-byte span difference**, and convergence did not touch it. The
|
**What is still open is the one-byte span difference**, and convergence did not touch it. The
|
||||||
guard excludes `<` from its negated class and the other two do not, so:
|
guard excludes `<` from its negated class and the other two do not. The three forms turn out to
|
||||||
|
be **totally ordered by what they match** — each a strict superset of the next:
|
||||||
|
|
||||||
| Witness | commons `0.7.0` / `llm-security` | guard |
|
| Witness | commons `0.7.0` / `llm-security` `[^>]` | guard `[^><]` | commons ≤ `0.6.0` |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `<script>steal()</script>` | match | match |
|
| `<script>steal()</script>` | match | match | match |
|
||||||
| `<script src=x.js>` | match | match |
|
| `<script src=x.js>` | match | match | no match |
|
||||||
| `<script>alert(1)` | match | match |
|
| `<script>alert(1)` | match | match | no match |
|
||||||
| `<script <x>` | **match** | **no match** |
|
| `<script\n src=x>` | match | match | no match |
|
||||||
|
| `<script a="<" >x` | **match** | **no match** | no match |
|
||||||
|
| `<script<div>` | **match** | **no match** | no match |
|
||||||
|
|
||||||
Measured by compiling all three forms, not reasoned from the character classes. The last row is
|
Measured by compiling all three forms, not reasoned from the character classes. The last two rows
|
||||||
the whole residual divergence and neither side has claimed it.
|
are the whole residual divergence.
|
||||||
|
|
||||||
|
The witness set and the ordering observation are `llm-security`'s, from their coord message of
|
||||||
|
2026-08-11T11:01:59Z; both were **reproduced here independently** before being recorded, including
|
||||||
|
the strict-superset property in both directions. Their reading of it: `[^><]` refuses to cross a
|
||||||
|
`<`, and since anything that reaches `[^>]`-and-not-`[^><]` already contains a literal `<script`
|
||||||
|
opening tag, the narrower class buys an empty false-positive surface in exchange for two dropped
|
||||||
|
input classes — a recall loss with no precision gain to trade for.
|
||||||
|
|
||||||
|
**That argument is recorded, not endorsed, and it did not decide commons' form.** Commons carries
|
||||||
|
`[^>]` because the lexicon's declared provenance is `llm-security`'s table (see above), not
|
||||||
|
because their regex won on merit — the same reasoning would have taken commons to `[^><]` had the
|
||||||
|
source been the guard's. `llm-security` asked to hear the guard's reason for `[^><]` — a ReDoS
|
||||||
|
bound, or a span-extraction consumer needing the run to stop at `<` — before commons shipped, and
|
||||||
|
commons shipped first. That order is deliberate rather than an oversight: a reason that beats this
|
||||||
|
argument is a reason for the *guard's own port*, and commons would still track its declared
|
||||||
|
source. Put to the guard as an open question 2026-08-11; unanswered at time of writing.
|
||||||
|
|
||||||
## Why they diverge: two different ReDoS mitigations of one table
|
## Why they diverge: two different ReDoS mitigations of one table
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue