Skip to content

fix(secrets): mask_secrets misses JSON/quoted-key credentials #549

Description

@boskodev790

mask_secrets misses the single most common structured shape a pasted credential takes — a JSON / quoted key — so it leaks into the capture buffer that becomes a committed session page and the append-only audit log.

wheresrc/vouch/secrets.py:40-44:

_ASSIGNMENT = re.compile(
    r"(?i)\b(api[_-]?key|secret|token|password|passwd|pwd|access[_-]?key)\b"
    r"(\s*[:=]\s*)"
    r"[\"']?[^\s\"']{6,}[\"']?"
)

The docstring/comment says it covers "key=value / key: value for sensitive-looking names — mask the value". But for "password": "hunter2secret" the name matches password, then the very next character is the key's closing quote ", while the separator group expects optional whitespace then :/=. The quote sits between them, so the match fails. A value that also isn't a recognized token format (a plain password, a short/custom key) then has no fallback and slips whole.

verified — regex and real pipeline:

mask  | "password=hunter2secret"      -> password=[redacted-secret]
mask  | "password: hunter2secret"     -> password: [redacted-secret]
LEAK  | '"password": "hunter2secret"' -> unchanged
LEAK  | "'api_key': 'abcdefghij'"     -> unchanged

Driving the real capture.observe path with {"password": "hunter2supersecret"} in an observation, the secret lands verbatim in .vouch/captures/<sess>.jsonl today — the gitignored buffer that rolls into a committed session page + audit log. That is exactly the file family vouch itself writes (.claude/settings.json via the install-adapter json_merge, config.yaml).

fix — allow an optional closing quote after the key name, folded into the captured separator group so the quote is preserved:

r"([\"']?\s*[:=]\s*)"

masks the leaking JSON/quoted-key forms ("password": [redacted-secret]), keeps every currently-working case masking, and adds no false positives (no-separator, sub-6-char value, quote-without-separator all stay untouched). happy to send it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions