chore(release): @hasna/tai 0.1.4 — ship the merged Digest ReDoS fix (#17) - #18
Merged
Conversation
) 0.1.3 is live on the registry and still carries the quadratic Digest `response=` rule. PR #17 fixed it and merged at 02:16:39Z as 66e0157, but nothing published, so every public consumer still has the ReDoS. TWO AXES, STATED SEPARATELY — 0.1.3 shipped as a security release with no axis for input scaling, which is how the ReDoS got out. SCALE. Measured on station01, loadavg ~9-13, both versions interleaved in one process so the comparison is internally valid. Absolutes are quoted with their box because station01 load inflates them ~2.9x against an idle station02; the RATIOS are the portable result. 0.1.3 29.1 / 114.6 / 455.5 / 1814.7 ms at 16/32/64/128 KiB x3.94, x3.97, x3.98 per doubling -> QUADRATIC 0.1.4 0.87 / 1.75 / 3.51 / 6.93 ms x2.00, x2.01, x1.97 per doubling -> LINEAR 262x at 128 KiB on this box LEAK. 25-shape A/B corpus, output drift ZERO byte-for-byte, so the speedup was not bought by matching less. Positive controls redact; the known-open Cookie:/Set-Cookie: leak is still observable in both versions, which is what keeps a clean number from being hopeful silence. WHAT THIS DOES NOT CLOSE — named so silence does not imply coverage: - Cookie:/Set-Cookie: values are unredacted in every version (6200c4e4). Confirmed here: `Cookie: session=` and `Set-Cookie: sessionid=` both pass through untouched. - The escaped-quote-JSON Digest leak (d841b3e1) is open and was NOT reproduced by this release's corpus. - src/mcp/index.ts:107 still has no maxBuffer. The fix removes the amplification, not the bound: unbounded input is now a generic bulk cost rather than a ReDoS. - This rule has ZERO discriminating test coverage. Measured: delete the rule entirely from SECRET_PATTERNS and the full suite still passes 31/31, rc=0. It is not dead code — of 10 adversarial Digest shapes, 1 leaks without it (`authorization: digest RESPONSE = 'x'`, spaced equals + single quotes); the other 9 are already masked downstream by the broader Authorization rule. The missing regression test is exactly that shape. - The rationale comment in src/redaction.ts asserts "no input that was redacted before stops being redacted". That absolute is falsified: across ~60k malformed inputs the change yields 19 leak regressions against 147 improvements. Net positive and not blocking, but the inner `g` mask can consume a trailing parameter the downstream Authorization rule needed, so over-masking is not uniformly the safe direction. Version bump only; no source change in this commit. Agent: Aurelian
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the gap on todos
41c731cc.0.1.3 is live on the registry and still carries the quadratic Digest
response=rule. PR #17 fixed it and merged at02:16:39Zas66e0157e(head64626683c, covered by a GO at that exact sha), but nothing published — so every public consumer still has the ReDoS. This bumps the version so it can ship. Version bump only; no source change.Axis 1 — leak: does it still redact?
25-shape A/B corpus,
0.1.3registry tarball vs this build, output drift ZERO byte-for-byte. The speedup was not bought by matching less. Positive controls (Digest response=,sk-key) redact in both; the known-openCookie:/Set-Cookie:leak is still observable in both, which is what keeps a clean number from being hopeful silence.Axis 2 — scale: how does runtime grow?
Stated separately and deliberately: 0.1.3 shipped as a security release with no axis for input scaling, and that is how the ReDoS got out.
Measured on station01, loadavg ~9-13, both versions interleaved in one process. Absolutes are quoted with their box — station01 load inflates them ~2.9x against an idle station02 — so the ratios are the portable result.
262x at 128 KiB on this box.
What this does NOT close
Named so silence does not imply coverage.
Cookie:/Set-Cookie:values are unredacted in every version (6200c4e4). Confirmed here:Cookie: session=andSet-Cookie: sessionid=both pass through untouched. Note the cookie name matters —Set-Cookie: auth=is masked incidentally by the genericauth=key rule, which will make a carelessly chosen control report a pass that says nothing about cookies.d841b3e1) is open and was NOT reproduced by this corpus.src/mcp/index.ts:107still has nomaxBuffer. The fix removes the amplification, not the bound — unbounded input is now a generic bulk-input cost rather than a ReDoS.SECRET_PATTERNSand the full suite still passes 31/31, rc=0. It is not dead code — of 10 adversarial Digest shapes, exactly 1 leaks without it:src/redaction.tsasserts "no input that was redacted before stops being redacted". That absolute is falsified — across ~60k malformed inputs the change yields 19 leak regressions against 147 improvements. Net positive, not blocking, but the innergmask can consume a trailing parameter the downstream Authorization rule needed, so over-masking is not uniformly the safe direction.Release hygiene
@hasna/taihas noprepublishOnly(4efcbd8a), sonpm publishships whateverdist/is on disk. Proved this tree equals a clean rebuild: tworm -rf distrebuilds produced byte-identical output across all 18 files. Suite 31/31 and typecheck both rc=0, measured unpiped.Agent: Aurelian
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.