Skip to content

fix(secrets): mask JSON/quoted-key credentials#550

Open
boskodev790 wants to merge 2 commits into
vouchdev:testfrom
boskodev790:fix/secrets-quoted-key-masking
Open

fix(secrets): mask JSON/quoted-key credentials#550
boskodev790 wants to merge 2 commits into
vouchdev:testfrom
boskodev790:fix/secrets-quoted-key-masking

Conversation

@boskodev790

@boskodev790 boskodev790 commented Jul 23, 2026

Copy link
Copy Markdown

What changed

mask_secrets now catches JSON / quoted-key credentials — "password": "...", 'api_key': '...'. one regex change: an optional closing quote after the sensitive-name group, folded into the captured separator so it's preserved in the output.

Why

fixes #549. the assignment regex expected the :/= immediately after the name, so a quoted key put its closing quote between the name and the separator and broke the match. a value that also matches no known token format (a plain password, a short/custom key) then slipped whole. this is the most common structured secret shape and exactly the file family vouch writes — .claude/settings.json (install-adapter json_merge) and config.yaml.

I drove the real capture.observe path with {"password": "hunter2supersecret"}:

  • before: the secret lands verbatim in .vouch/captures/<sess>.jsonl — the gitignored buffer that rolls into a committed session page and the append-only audit log
  • after: masked to [redacted-secret], key name and quotes kept legible

What might break

nothing on disk, no kb.* behaviour change. the change only widens which strings get masked. verified against a matrix: all 3 leaking JSON/quoted-key forms now mask; all 4 currently-masked forms still mask (no regression); and 3 false-positive guards stay untouched — a name with no separator ("password" is required), a value under the 6-char floor (password: hi), and a quoted word without an assignment. the only visible change is that a previously-leaked credential is now redacted, which is the intent.

VEP

not a surface change — no kb.* method, object model, on-disk layout, bundle format or audit-log shape touched. secrets.py is non-core. no VEP.

Tests

  • make check passes locally (lint + mypy + pytest) — 1680 passed, 50 skipped; ruff clean; mypy clean across 104 source files
  • New / changed behaviour has a test
  • CHANGELOG.md updated under ## [Unreleased]

test_masks_json_and_quoted_key_credentials — verified failing on test without the src change (the secret leaks); passing with it. test_quoted_key_masking_no_false_positive pins the guards. Also drove the end-to-end capture.observe pipeline both ways to confirm the buffer no longer receives the credential.

no ui surface touched, so no screenshots.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed secret masking to correctly detect and redact credentials in structured JSON/YAML-style “quoted key” formats (including quoted keys before the :).
    • Ensured sensitive values are masked during capture so they no longer end up in session pages or the append-only audit log.
    • Added coverage to prevent false positives and avoid masking non-credential or too-short values.
  • Documentation

    • Updated the changelog to describe the improved credential masking behavior.

the assignment regex expected the separator (: or =) immediately after a
sensitive-looking name, so a quoted key put its closing quote between the
name and the separator and broke the match. "password": "..." and
'api_key': '...' — the most common structured secret shape, and exactly
the file family vouch writes (settings.json, quoted yaml) — slipped
through mask_secrets into the gitignored capture buffer that rolls into a
committed session page and the append-only audit log.

allow an optional closing quote after the name, folded into the captured
separator group so the quote is preserved in the output. every
currently-masked case still masks; no new false positives (no separator,
value under the 6-char floor, or a quoted word without an assignment stay
untouched).
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a5024fc5-170e-4622-93ca-2548e193b10f

📥 Commits

Reviewing files that changed from the base of the PR and between 9b0a0e3 and ee80012.

📒 Files selected for processing (1)
  • src/vouch/secrets.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/vouch/secrets.py

Walkthrough

Secret masking now recognizes JSON and quoted-key credential assignments. Tests cover successful redaction and false-positive cases, and the changelog documents the fix.

Changes

Secret masking

Layer / File(s) Summary
Quoted-key assignment masking
src/vouch/secrets.py, tests/test_secrets.py, CHANGELOG.md
The assignment regex handles optional quotes between sensitive keys and separators. Tests verify masking, contains_secret, preserved key labels, and non-matching short or separator-less values. The changelog records the fix.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • vouchdev/vouch#551: Updates the same secret-assignment regex and adds related quoted-key masking tests.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title concisely and accurately describes the main change: masking JSON and quoted-key credentials.
Linked Issues check ✅ Passed The regex, tests, and changelog updates address the linked issue's masking, preservation, and false-positive requirements.
Out of Scope Changes check ✅ Passed The changes appear limited to the requested secrets-masking fix, its tests, and the changelog note.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added docs documentation, specs, examples, and repo guidance tests tests and fixtures size: XS less than 50 changed non-doc lines labels Jul 23, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 `@src/vouch/secrets.py`:
- Around line 39-43: Update the newly added comment prose in the affected
section of secrets.py so sentence starts remain lowercase, including “the,”
“without,” and “it,” while preserving the existing technical explanation and
code behavior.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fd62cd8c-5d6a-4f28-993a-f146f55615ce

📥 Commits

Reviewing files that changed from the base of the PR and between 3beed68 and 9b0a0e3.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • src/vouch/secrets.py
  • tests/test_secrets.py

Comment thread src/vouch/secrets.py Outdated
the added assignment-masking comment started sentences with capitals
and used JSON/YAML uppercase; src/vouch/** requires lowercase comment
prose. no behaviour change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs documentation, specs, examples, and repo guidance size: XS less than 50 changed non-doc lines tests tests and fixtures

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants