fix(security): always block the age key and PEM private keys even when secretScan=off - #190
Conversation
…Scan=off secretScan="off" previously disabled all push-time secret detection, including the vault's own age secret key and PEM private keys. Committing the age key (even encrypted to recipients) lets any future reader decrypt the entire vault, irreversibly. Add an always-block catastrophic tier (ALWAYS_BLOCK_PATTERNS, derived from EMBEDDED_SECRET_PATTERNS by name) that fires in every mode; off now scans exactly that tier, waiving only the ordinary API-token patterns. standard/strict are unchanged. Also close an allow-list bypass found in review: the catastrophic tier is now non-exemptible in scanForSecrets, and `config set` scans the allowSecretValues value itself for catastrophic literals before storing. Refs #181 (1 of 2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011L7s33UCjpQkreXW7amAw2
|
Warning Review limit reached
More reviews will be available in 40 minutes and 14 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?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 credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. 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, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughIntroduces a "catastrophic tier" (age secret key + PEM private key) that ChangesCatastrophic-tier secret enforcement
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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 |
CI runs biome 2.4.15 which collapses the arrow body and reflows the long expect() in the two new catastrophic-tier tests. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011L7s33UCjpQkreXW7amAw2
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@docs/commands.md`:
- Around line 379-380: The documentation for the `security.allowSecretValues`
configuration option on line 380 currently describes it as a blanket
literal-value exemption from secret detection, which is misleading given that
line 379 explicitly states catastrophic tier secrets (age keys, PEM private
keys) always block. Clarify the `security.allowSecretValues` description to
explicitly scope the exemption to ordinary-token detection patterns only, and
make it clear that catastrophic tier secrets cannot be allow-listed regardless
of this setting. This ensures the documentation accurately reflects that only
standard credential patterns are eligible for exemption through this option.
In `@src/commands/config.ts`:
- Around line 173-176: The scanForSecrets function is validating the rawValue
before parsing, but the actual persisted value is parseScalar(rawValue),
creating a gap where encoded secrets could bypass validation. Change both calls
to scanForSecrets (the one with the SECRET_EXEMPT_KEY condition and the else
case) to pass parseScalar(rawValue) instead of rawValue, ensuring the secret
scanning occurs on the decoded value that will actually be stored rather than
the raw encoded form.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 48f63da6-317b-4abe-915b-fdb6d2d7d634
📒 Files selected for processing (8)
docs/commands.mddocs/operations.mdsrc/agents/skills-walker.tssrc/commands/__tests__/config.test.tssrc/commands/config.tssrc/config/schema.tssrc/core/__tests__/sanitizer.test.tssrc/core/sanitizer.ts
…owlist docs Address CodeRabbit review on PR #190: - config set scanned rawValue but persisted parseScalar(rawValue), so a JSON-escaped age key (e.g. AGE-SECRET-KEY-…) passed the raw scan yet decoded to a real secret on disk. Scan the decoded value(s) instead; for allowSecretValues, scan each decoded array element. Adds a regression test. - docs: allowSecretValues is exempt from ordinary-token detection only; catastrophic-tier values are never exemptible. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011L7s33UCjpQkreXW7amAw2
Summary
Fixes the first half of #181:
secretScan = "off"previously disabled all push-time secret detection — including the vault's own age secret key and PEM private keys. Committing the age key (even encrypted to recipients) hands every future reader the means to decrypt the entire vault, retroactively and irreversibly. That can never be safe, regardless of mode.This adds an always-block catastrophic tier that fires in every mode:
ALWAYS_BLOCK_PATTERNS(age-secret-key,private-key-pem) is derived fromEMBEDDED_SECRET_PATTERNSby name, so each regex body stays defined once.scanForSecretsno longer early-returns[]foroff—offnow scans exactly the catastrophic tier, waiving only the ordinary API-token patterns.standard/strictselection is byte-for-byte unchanged.Security hardening from review
A senior-review pass caught that the catastrophic tier was still bypassable via
allowSecretValues: the allow-list exemption was applied to every pattern, andconfig setdeliberately skips its own leak-scan for that key. Soconfig set security.allowSecretValues '["AGE-SECRET-KEY-1…"]'would have landed the master key in plaintextagentsync.tomland silenced it at push. Closed two ways:scanForSecrets: catastrophic hits are never exemptible (catastrophic || !allow.includes(…)).config set: theallowSecretValuesvalue is itself scanned for the catastrophic tier (off-mode scan) before being stored.Tests
standard/strict/offallowSecretValuescan not exempt a catastrophic valueoff;ALWAYS_BLOCK_PATTERNSinvariantconfig set security.allowSecretValuesrejects an age keyFull suite: 980 pass / 0 fail.
Scope
First of two PRs for #181. This is the independent security-footgun fix. The
redactmode (redact API keys and push, instead of blocking) plus placeholder-awarecopyand the TUI surfacing follow in a second PR.🤖 Generated with Claude Code
https://claude.ai/code/session_011L7s33UCjpQkreXW7amAw2
Summary by CodeRabbit
Bug Fixes & Security
security.secretScansetting.Documentation
security.secretScanbehavior: the "off" mode explicitly waives ordinary API-token patterns while maintaining protection against catastrophic-tier secrets in all modes.