Parent: #1936
Problem
src/review/safety.ts's secretLeakFinding() produces the ALWAYS-ON, unconditional secret_leak hard gate blocker (regardless of any repo opt-in — this fires for every repo, every PR) but only recognizes 5 concrete patterns via HARD_SECRET_KINDS: github_token, github_pat, private_key_block, aws_access_key, slack_token.
Meanwhile review-enrichment/src/analyzers/secret-scan.ts (shipped under #1476, "gitleaks-grade secret scan analyzer with value redaction") already has a richer, higher-recall rule set: Google API keys (AIza...), JWTs, and a generic secret/password/client_secret/api_key-assignment pattern. That richer scanner only feeds the AI reviewer's advisory write-up (the REES enrichment brief), which requires AI review to be enabled (off by default) — it is NOT reused by the deterministic hard blocker.
So a leaked Google API key, Stripe/OpenAI/Anthropic-style key, JWT, or a plain password = "..." assignment — patterns this repo has ALREADY built detection for — sails through the deterministic gate clean today, on every repo, regardless of AI-review config.
Requirements
- Extract the richer rule set from
review-enrichment/src/analyzers/secret-scan.ts into a shared module both the REES analyzer and src/review/safety.ts's hard blocker can import from (no duplicated pattern lists).
- Fold the additional patterns (Google API keys, JWTs, generic secret/password/token/client_secret assignments) into
HARD_SECRET_KINDS, preserving the existing always-on, unconditional-block semantics — this must not become opt-in.
- Preserve existing value-redaction behavior (never echo the actual secret value in a public comment/blocker message).
- Tune the generic
secret/password-assignment pattern carefully to avoid excessive false positives (e.g. password: z.string() in a Zod schema, secretKey as a variable/type name with no literal value) — this is the main risk of widening a hard, unconditional blocker.
Deliverables
- A shared secret-pattern module consumed by both
src/review/safety.ts and review-enrichment/src/analyzers/secret-scan.ts.
- Updated
HARD_SECRET_KINDS in src/review/safety.ts including the new pattern kinds.
- Tests: positive cases for each new pattern kind (Google API key, JWT, generic assignment) triggering the hard blocker; negative cases proving common false-positive shapes (type declarations, schema definitions, redacted/placeholder values like
"xxx" or "<REDACTED>") do NOT trigger it.
Acceptance criteria
- A PR introducing a real Google API key, JWT, or a literal
password = "..."/secret = "..." assignment is hard-blocked by the deterministic gate, with no AI-review opt-in required.
- No measurable increase in false-positive hard-blocks against the existing test corpus / a sample of recent merged PRs.
- No secret value is ever echoed in the public blocker message.
Expected outcome
The deterministic, always-on secret-leak gate blocker actually matches the detection capability this repo has already built and shipped in REES — closing the gap where a real credential leak currently depends on whether AI review happens to be enabled for that repo.
Parent: #1936
Problem
src/review/safety.ts'ssecretLeakFinding()produces the ALWAYS-ON, unconditionalsecret_leakhard gate blocker (regardless of any repo opt-in — this fires for every repo, every PR) but only recognizes 5 concrete patterns viaHARD_SECRET_KINDS:github_token,github_pat,private_key_block,aws_access_key,slack_token.Meanwhile
review-enrichment/src/analyzers/secret-scan.ts(shipped under #1476, "gitleaks-grade secret scan analyzer with value redaction") already has a richer, higher-recall rule set: Google API keys (AIza...), JWTs, and a genericsecret/password/client_secret/api_key-assignment pattern. That richer scanner only feeds the AI reviewer's advisory write-up (the REES enrichment brief), which requiresAI reviewto be enabled (off by default) — it is NOT reused by the deterministic hard blocker.So a leaked Google API key, Stripe/OpenAI/Anthropic-style key, JWT, or a plain
password = "..."assignment — patterns this repo has ALREADY built detection for — sails through the deterministic gate clean today, on every repo, regardless of AI-review config.Requirements
review-enrichment/src/analyzers/secret-scan.tsinto a shared module both the REES analyzer andsrc/review/safety.ts's hard blocker can import from (no duplicated pattern lists).HARD_SECRET_KINDS, preserving the existing always-on, unconditional-block semantics — this must not become opt-in.secret/password-assignment pattern carefully to avoid excessive false positives (e.g.password: z.string()in a Zod schema,secretKeyas a variable/type name with no literal value) — this is the main risk of widening a hard, unconditional blocker.Deliverables
src/review/safety.tsandreview-enrichment/src/analyzers/secret-scan.ts.HARD_SECRET_KINDSinsrc/review/safety.tsincluding the new pattern kinds."xxx"or"<REDACTED>") do NOT trigger it.Acceptance criteria
password = "..."/secret = "..."assignment is hard-blocked by the deterministic gate, with no AI-review opt-in required.Expected outcome
The deterministic, always-on secret-leak gate blocker actually matches the detection capability this repo has already built and shipped in REES — closing the gap where a real credential leak currently depends on whether AI review happens to be enabled for that repo.