Repository navigation
Semgrep: flag body caps checked after a whole read and forwarded-header limiter keys - #2162
Merged
Merged
Conversation
…er limiter keys templates/semgrep-taint/js.yml gains two INFO rules for resource exhaustion. perun.js.body-cap-after-buffer reports `await <receiver>.formData()`, `.json()`, `.text()` or `.arrayBuffer()` on a receiver named like req or request (req, request, c.req, ctx.request, event.request) when the same block later compares the result's .size, .length or .byteLength, directly or on an entry read with .get(...), against a cap, or when only a content-length comparison precedes the read. The whole body is already in memory when such a cap runs, and a declared length does not bound a chunked body; the message points to reading the stream with getReader() and stopping at a running byte total. A comparison with the literal 0 is an emptiness check and is not reported, and neither is a read on res, response or file. perun.js.limiter-key-forwarded-header reports an x-forwarded-for or x-real-ip read (headers.get, headers.header or headers[...]) inside a function named like clientKey, limiterKey, rateKey, deriveKey or getIp. The message asks the reviewer to check that only entries added by trusted proxies are used, that a missing header does not map every caller onto one shared key, and that a missing header does not fail open. Both rules skip the test, fixture and mock paths the sibling rules skip. Their ceilings are ponytail: lines in the js.yml header: receiver and function names are heuristics; only a > comparison with the result on the left is recognised; a destructured, inline, optional-chained or non-null-asserted result is not tied to a later check; a read and its check in different blocks are not tied; and a cap enforced in middleware or a framework option is invisible. New test scripts/test_semgrep_taint_ext.py, registered as scripts/ci-tests.d/semgrep-taint-ext.sh. The live part runs when semgrep is installed: in annotated fixtures a `// ruleid:` line must be reported and an `// ok:` or unannotated line must stay clean, copies of the fixtures under test paths must stay clean, and a copy of the rules with an invalid severity must be rejected, which checks the rule schema without contacting semgrep.dev. The offline part always runs: severity, languages, message keywords and skipped paths of each rule, the header ceiling lines, the whole pattern skeleton of each rule compared with the rule text, and replays of the rules' regexes on positive and negative values. CI installs no semgrep, so CI runs the offline part. Tests: test_semgrep_taint_ext ok live (semgrep 1.182.0) and offline (semgrep removed from PATH), test_semgrep_taint ok live; 9 of 9 sections passed (run-ci-tests.sh --affected e91de69, privacy and trigger lint included); size ratchet, fragments gate, privacy and identity gates clean. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Wave 14 adds two INFO semgrep rules for resource exhaustion: a request body capped only after it is read whole, and a rate-limit key built from a forwarded header.
What changes
perun.js.body-cap-after-buffer:await req.json()(orformData,text,arrayBuffer) on a request-named receiver, then a.size,.lengthor.byteLengthcap in the same block, or only acontent-lengthcheck before the read. Emptiness checks against0and reads onres,responseorfileare not reported.perun.js.limiter-key-forwarded-header: anx-forwarded-fororx-real-ipread inside a function named like a limiter key.ponytail:lines in thejs.ymlheader.scripts/test_semgrep_taint_ext.py: annotated fixtures run live when semgrep is installed; skeleton pins and regex replays always run (CI runs this part).Verification
test_semgrep_taint.pypasses live.> 0and non-request receivers, missing path skips, incomplete offline pins) are fixed here.This PR is the first of three
perprkeep-bar checks for #2161.🤖 Generated with Claude Code