Close the split-token and reflection bypasses, and self-test the guard - #473
Conversation
|
Warning Review limit reached
Next review available in: 35 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
WalkthroughThe RNG hygiene guard now handles split member access, concatenated class names, and reflective loading. A self-test harness validates rejection and acceptance cases in an isolated Git index. CI runs the harness before the existing hygiene check. ChangesRNG hygiene validation
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant CI
participant TestHarness as test-rng-hygiene.sh
participant Guard as check-rng-hygiene.sh
participant GitIndex as temporary Git index
CI->>TestHarness: Run RNG hygiene self-test
TestHarness->>GitIndex: Stage a temporary probe
TestHarness->>Guard: Check the staged probe
Guard-->>TestHarness: Return detection result
TestHarness->>GitIndex: Remove the temporary probe
TestHarness-->>CI: Return pass or failure
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/test-rng-hygiene.sh`:
- Around line 45-46: Update the temporary-index setup in the test harness to
check the exit status of both `git read-tree` and `git add` instead of
suppressing failures. Record a harness failure when either command fails, before
invoking the guard, and prevent stale `$staged` contents from being treated as a
successful pass.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 0e4b18f8-88c8-44e7-8d39-0aa78dab2374
📒 Files selected for processing (3)
.github/workflows/ci.ymlscripts/check-rng-hygiene.shscripts/test-rng-hygiene.sh
|
Valid, fixed here and in the same harness in privkeyio/keep#936, which is still open. The Now asserted directly: if ! GIT_INDEX_FILE="$TMPD/index" git ls-files --error-unmatch "$name" >/dev/null 2>&1; then
echo " HARNESS BROKEN: $name was not staged; the guard would never see it"Verified by sabotage rather than by reading: replaced the That is the third harness defect found in this pattern, after the exit-code-only check and the two-line probes in keep-node#108. Each had the same shape: the test reaching a verdict without having established the conditions the verdict depends on. Worth noting since the same harness now runs in four repositories. The two already merged, keep-node#108 and keep-esp32#154, carry this same gap. Following up there separately rather than leaving the four copies divergent. |
Summary
Two ways to reach a banned generator without the scanner seeing it. Both closed, plus
scripts/test-rng-hygiene.shso the rules are asserted rather than assumed.The bypasses
Reproduced against a positive control that does fail. Probes under
app/src/main/kotlin, which matters: the guard deliberately skipstest,androidTestandtestFixtures, so a probe placed there passes and looks like a bypass when it is only misplaced. My first attempt did exactly that, and the control is what caught it.Math.random()(control)Math.newlinerandom()java.util.newlineRandom()Class.forName("java.util." + "Random")classLoader.loadClass("java.util.Random")Split member access. Kotlin continues an expression after a trailing dot, so
Math.andrandom()on separate lines are the same call. The guard already buffered across unbalanced parentheses; a trailing dot now continues the buffer the same way. The join is deliberately without a separator: reassembling asMath. random()still fails to matchMath[.]random, which is the bug the first version of this fix had.Reflection. A class name built by concatenation defeats any literal match, and
Class.forNamereaches the same PRNG. There is no legitimateClass.forNameorloadClassin production sources today (checked), so the rule is simply: don't, with a marker available if that changes.Why this class keeps appearing
Third repository this week with the same shape. keep-node #108: variable indirection and string concatenation past a line matcher. keep-esp32 #154: a C line continuation splitting an identifier. Here: a Kotlin member access splitting a call. A line-oriented scanner loses to anything that splits the token, so each language needs its own splice rule, and each needs a test that says so.
The self-test
Ported from keep-esp32, keeping the two properties that make it trustworthy:
WRONG REASONrather than credited as a detectionTen cases: seven rejections including both split forms, both reflection routes,
setSeedandThreadLocalRandom; three acceptances.Test plan
Class.forName/loadClassbefore making it a hard rulebash -nclean,ci.ymlparses, release-changelog gate still passesNot claimed: this closes known evasions, it does not make a line-oriented scanner undefeatable.
Summary by CodeRabbit
Tests
Chores