Fix polynomial ReDoS in request-text parsing, tighten token file mode - #176
Merged
Conversation
teamchong
force-pushed
the
security/code-scanning-followup
branch
2 times, most recently
from
August 4, 2026 01:33
37cad9d to
d1d11c1
Compare
Three parsers walked untrusted request text with patterns that restart at every candidate position, so cost was quadratic in input length. The <env> and static-tag bodies used a lazy [\s\S]*? span, the static-tag scan also matched openings with (?:\s[^>]*)?>, and minifyForRender stripped line ends with /[ \t]+$/. Worst case is text that never satisfies the pattern: 80k repeats of '<A ' took 18s, one 400KB line of spaces took 76s. All three scan by index instead. Behaviour is unchanged, checked by differential fuzzing against the original regexes and by comparing the new character classifiers against /[a-zA-Z0-9_-]/ and /\s/ across the BMP. run_shard.py wrote the OAuth token file under the default umask and chmod'd it to 0600 afterwards, leaving it briefly readable by other users on the host. Open it 0600 instead.
teamchong
force-pushed
the
security/code-scanning-followup
branch
from
August 4, 2026 01:45
d1d11c1 to
89fb91a
Compare
qbq-leo-martens
pushed a commit
to qbq-leo-martens/pxpipe
that referenced
this pull request
Aug 5, 2026
…-history page breaks (teamchong#178), warp host:port routes (teamchong#175), macOS restart fix
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.
Nineteen code-scanning alerts. Four were real, fixed here. Fifteen were dismissed on the alert after measuring them.
Fixed
Three parsers walked untrusted request text with patterns that restart at every candidate position, so cost was quadratic in input length. Worst case is text that never satisfies the pattern, which is what a malformed or truncated body looks like.
<env>body'<A ' x80000minifyForRenderThe
<env>and static-tag bodies used a lazy[\s\S]*?span, which rescans the tail once per candidate opening. The static-tag scan had a second, independent quadratic: matching openings with(?:\s[^>]*)?>rescans the tail once per candidate tag when no>follows. Fixing only the span left the alert open, which is what CodeQL caught on the first revision of this PR. Both now scan by index.minifyForRenderwalks back from the end of the line.run_shard.pywrote the OAuth token file under the default umask and chmod'd it to 0600 afterwards, leaving it briefly readable by other users on the host. It is opened 0600 now. Caching the token on disk is deliberate, the proxy re-reads it per request so a task can outlive its token.Dismissed
Twelve of the remaining ReDoS reports are anchored on a required literal prefix, which bounds the ambiguity. Measured flat under 1ms from 5KB to 640KB on matching, non-matching, and repeated-prefix inputs. Two of them (
applicability.ts:23,gpt-model-profiles.ts:525) gate model selection and are deliberately identical to each other, so rewriting them to satisfy the scanner risks a routing regression for no measured gain. Theproxy.tsandmessages-chat-bridge.tspatterns normalize config URLs read at startup, not request data.node.ts:1293logs the cloudflare upstream URL, built only as.../accounts/${cfAccount}/ai/v1. That is the account id, not a credential.CLOUDFLARE_API_TOKENis passed separately and never interpolated.Checks
Behaviour is unchanged, not just green. The rewrites were differentially fuzzed against the original regexes (500k cases for the tag scan, 400k for
minifyForRender, no mismatches), and the hand-written character classifiers were compared against/[a-zA-Z0-9_-]/and/\s/across all 65536 BMP codepoints. That last check caught a real bug: I had included U+0085, which JS/\s/does not match.tests/redos-guard.test.tsfails on the unfixed code, the tag-scan guard at 15.3s against a 5s budget, so it is a regression net rather than a restatement of the implementation.The four fixed alerts stay open until CodeQL rescans after merge.