fix(review): widen the gate's hard-blocking secret scan to match REES's richer ruleset - #2613
Conversation
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-02 16:51:44 UTC
⏸️ Suggested Action - Manual Review
Review summary Nits — 7 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2613 +/- ##
=======================================
Coverage 96.02% 96.03%
=======================================
Files 233 233
Lines 26077 26096 +19
Branches 9474 9481 +7
=======================================
+ Hits 25041 25060 +19
Misses 425 425
Partials 611 611
🚀 New features to boost your workflow:
|
A string with no repeated characters (e.g. "abcdefghijklmnop123") has high Shannon entropy by raw character-frequency counting, but is obviously not a real secret since entropy alone measures frequency, not order. A keyboard-sequential or alphabetical run slipped past the prior distinct- character-count placeholder check. Detect the longest run of consecutive ascending or descending character codes and treat a 6+ character run as a human-constructed test value rather than a randomly generated credential.
1b1693a to
dc1496c
Compare
) PR #5346 (a resubmission of #5341) was auto-closed over two inert test-fixture strings that matched the generic_secret_assignment keyword-plus-quoted-value SHAPE but weren't real credentials -- the same heuristic has now caused at least eight prior false-positive incidents (#2613, #3178, #3673, #3866, #4587, #4733, plus several fixture-rewording commits), each patched by narrowing an allowlist rather than fixing the underlying design. REES's own copy of this rule already rates it "medium confidence" ("catches real keys but also the occasional long opaque non-secret"), and content-lane/security-scan.ts's own header states the design principle this violated: a gate that auto-closes with no human queue may only hard-close on a signal unambiguous enough that a false positive is essentially impossible. Split generic_secret_assignment out of HARD_SECRET_KINDS into a new ADVISORY_ONLY_SECRET_KINDS: it still surfaces (a warning-severity possible_secret_assignment finding / a "manual" content-lane verdict), but never auto-blocks or auto-closes on its own. Concrete credential formats (github_token, aws_access_key, private_key_block, ...) are unaffected and remain unconditional hard blockers. Also add a structural placeholder heuristic (looksLikeDescriptive PlaceholderPhrase, mirrored in REES): a value with 5+ lowercase-only hyphen/underscore segments containing an English function word reads as written prose describing the value, not a credential or a chosen passphrase -- this independently resolves both PR #5346 literals without weakening detection of a genuine human-chosen passphrase like "correct-horse-battery-secret" (no function words, by design).
Summary
src/review/safety.ts'ssecretLeakFinding()— the ALWAYS-ON, unconditionalsecret_leakhard blocker that fires for every repo, every PR regardless of any opt-in — only recognized 5 concrete patterns viaHARD_SECRET_KINDS:github_token,github_pat,private_key_block,aws_access_key,slack_token.review-enrichment/src/analyzers/secret-scan.ts(feat(enrichment): gitleaks-grade secret scan analyzer with value redaction #1476) already has a richer, higher-recall rule set: Google API keys, JWTs, and a generic secret/password/token-assignment pattern. That richer scanner only fed the AI reviewer's advisory write-up (AI review off by default), never the deterministic hard blocker — so a leaked Google API key, JWT, or a plainpassword = "..."assignment sailed through the gate clean on every repo.Scope
src/review/secrets-scan.ts— widenedSECRET_PATTERNSto addgoogle_api_keyandjwt(format-precise, same near-zero false-positive risk as the existing 5) plusgeneric_secret_assignment— the one keyword-shaped pattern, so it needs real guardrails before becoming an unconditional blocker:isPlaceholderSecretValuerejects placeholder phrases (your-,changeme,redacted,example,<...>, etc.) and low-entropy filler ("xxxxxxxxxxxxxxxx") before a match counts, and the 16+ character floor already excludes short type/schema declarations likepassword: z.string()(no quoted literal to match at all).src/review/safety.ts— added the 3 new kinds toHARD_SECRET_KINDS.review-enrichmentdeploys standalone on Railway with its own tsconfig/build/test pipeline, so importing across that boundary would break its independence — the same reasoningsecrets-scan.ts's own header already documents for staying self-contained relative to reviewbot.src/review/content-lane/security-scan.ts, a separate self-contained copy for the unrelated content-submission feature — out of scope for this issue.Validation
npx vitest run test/unit/secrets-scan.test.ts test/unit/safety-wiring.test.ts test/unit/safety.test.ts— 48/48 passing, 100% line/branch coverage on the changed filesnpm run typecheck— cleannpm run test:ci— full local gate greennpm audit --audit-level=moderate— 0 vulnerabilitiesSafety
Closes #2553