release(0.3.3): the lexicon ReDoS fix, and a correction to 0.3.2's claim
Version synced across the four locked points (pyproject, __version__, README badge, README install pin) + CHANGELOG. Corrections this release carries, both measured rather than reasoned: - docs/LIMITATIONS.md said the script-tag change removed "the last" quadratic-backtracking site on the output path. It did not. Corrected, with the 334.7s gate measurement that falsifies it. - README's coverage line claimed 126/126 classes; the matrix reports 128/128. Stale since before v0.3.2. Test badge was 642, actual 666. New residual recorded (LIMITATIONS, now 30 items, README synced): the sweep flags on timing above a 1.5ms noise floor at N=8000, so an arm hiding under it could still cost ~23s at the cap. What this supports is "no arm worse than ~23s", not "no quadratic arm remains" -- and the blind spot is demonstrated, since a generic-payload pass found only one of the two patterns. 666 tests green, coverage matrix 128/128 with 6/6 gaps holding, exit 0.
This commit is contained in:
parent
b8028ba870
commit
701a4a47c7
5 changed files with 105 additions and 8 deletions
|
|
@ -249,7 +249,12 @@ items; this is the full list, each with the mechanism.
|
|||
document *about* XSS is flagged alongside a document that *carries* it. This
|
||||
is a deliberate trade made twice over: requiring the closing tag was a
|
||||
fail-open (an unclosed `<script>alert(1)` was silently missed by *this label*)
|
||||
and it was the last quadratic-backtracking site on the output path.
|
||||
and it removed a quadratic-backtracking site on the output path. **It was not
|
||||
the last one** — 0.3.2 said so and that claim was wrong. The 0.3.3 sweep of
|
||||
all 83 lexicon patterns found two more, and because `scan_lexicon` runs on the
|
||||
output path too, they were reachable through `scan_output`: `"[" * 100_000`
|
||||
took 334.7s through the gate. The claim was too broad because the sweep behind
|
||||
it drove `[` only through `scan_active_content`, never through the lexicon.
|
||||
**Measured, both claims are narrower than they read.** The new label costs no
|
||||
consumer a disposition: any text containing a literal `<script>` already
|
||||
produced `active:raw-html` at HIGH on 0.3.1 — so the same prose disposed
|
||||
|
|
@ -275,6 +280,19 @@ items; this is the full list, each with the mechanism.
|
|||
`PRESET_USER_UPLOAD` it still `fail_secure`s. The credential is never silently
|
||||
missed; on one preset it is held for review instead of halted.
|
||||
|
||||
- **The ReDoS sweep of the lexicon has a measured sensitivity floor, not a clean
|
||||
bill of health.** All 83 patterns were swept arm by arm — payloads synthesised
|
||||
per run from each pattern's own skeleton, so `[`, `[system]` and `[system](`
|
||||
are each probed separately rather than relying on generic units. Two patterns
|
||||
were quadratic and both are fixed. But the sweep flags on *timing*, and it
|
||||
ignores measurements below a 1.5 ms noise floor at N=8000. A quadratic arm
|
||||
sitting just under that floor would still cost **up to ~23 s** at the
|
||||
1 000 000-char cap the gate accepts. So the claim this sweep supports is
|
||||
"no arm worse than ~23 s at the cap", not "no quadratic arm remains". The
|
||||
method's blind spot is real and was demonstrated in this very sweep: a
|
||||
generic-payload pass found only one of the two patterns, and the second
|
||||
surfaced only after the payloads were generated per run.
|
||||
|
||||
## The six documented gaps (tracked by the coverage matrix)
|
||||
|
||||
These are asserted to *still hold* by `tests/test_coverage_matrix.py` — a closed gap
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue