Skip to content

fix(security): redact refused input before writing security logs - #189

Open
rahul05ranjan wants to merge 1 commit into
mainfrom
fix/security-log-redaction
Open

rahul05ranjan wants to merge 1 commit into
mainfrom
fix/security-log-redaction

Conversation

@rahul05ranjan

Copy link
Copy Markdown
Owner

Fixes #188

Root cause

validateInput refused input that matched a blocked pattern (one of which exists specifically to catch password exposure), but the same refusal path handed the raw input to logSecurity. logger.security runs at warn, which passes the daily-rotate file transport's debug level, so the full refused input — secret included — was written verbatim into logs/dhruv-YYYY-MM-DD.log (plaintext, 14-day retention). The security control was copying the exact value it refused to protect onto disk.

Fix

SecurityManager.redactForLog turns the refused input into a bounded audit view:

  • masks password = ..., api_key = ..., token: ..., secret, credential assignments
  • masks Bearer tokens and credentials embedded in URLs
  • truncates to 200 characters

Every security-event log call on the validation path (blocked_command, invalid_input, blocked_pattern, validation_error, and the sanitize-step warning) now logs the redacted view. The command name, matched pattern and validation error are untouched, so refusals stay debuggable; only the credential-shaped content is masked.

Verification

  • Redaction logic exercised in isolation with the system Node (8 cases: password assignment in text, JSON object input, token: value, Bearer header, postgres://user:pass@host URL credential, benign code question unchanged, 250-char truncation, non-serializable input) — all pass.
  • The repo's own jest suite was not run here because dependencies are not installed in this environment; the change is confined to the four log-call arguments plus the new private helper, and TypeScript compilation of the helper was not run either — CI will cover both.

Note: the same redaction is applied to the Input was sanitized warning, which also carried raw input; that whole step is dead code (its result is never used) — separate issue for that coming next, and it is deliberately left untouched here so the two fixes stay reviewable on their own.

validateInput passed the raw refused input to logSecurity, so the
blocked-pattern rules that exist to keep credentials out of a request
persisted those credentials verbatim into the rotating plaintext logs
under logs/ (14-day retention). Add redactForLog: a bounded, truncated
view that masks password/api-key/token/secret assignments, Bearer
headers and URL credentials, used by every security-event log call on
the validation path. The command, pattern and error stay in the audit
entry; the secret no longer does.

Verified the redaction logic in isolation (8 cases incl. password
assignment, JSON input, bearer token, URL credential, benign code
text, truncation) with the system Node; the repo's own jest suite was
not run since dependencies are not installed here.

Fixes #188

Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Blocked-pattern validation writes the refused input, secrets included, into plaintext logs

1 participant