Skip to content

fix: redact PII in user-data error logging#489

Open
narutamaaurum wants to merge 4 commits into
piyushdotcomm:mainfrom
narutamaaurum:fix/user-data-pii-redaction
Open

fix: redact PII in user-data error logging#489
narutamaaurum wants to merge 4 commits into
piyushdotcomm:mainfrom
narutamaaurum:fix/user-data-pii-redaction

Conversation

@narutamaaurum

@narutamaaurum narutamaaurum commented Jun 9, 2026

Copy link
Copy Markdown

Closes #274

This PR addresses CodeRabbit review comments on #488 by adding PII redaction to error logging in lib/user-data.ts.

Changes:

  • Added function that masks sensitive keys (email, phone, ssn, password, token, secret, key, auth, credential)
  • Applied redaction in function before logging params

This ensures emails and other sensitive data are not logged in error messages.

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling for user-data retrieval with structured error logs that include timestamp, context, and stack information.
    • Added automatic redaction of sensitive information in error logs to protect personal data.

- Replace bare catch blocks with proper error capture and structured logging
- Log errors with function name and query parameters for observability
- Rethrow errors so callers can differentiate DB failures from not-found results
- Follow existing structured logging pattern from lib/api-utils.ts

Addresses CodeRabbit review on PR piyushdotcomm#488
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Adds recursive sensitive-key redaction and a structured logError helper to lib/user-data.ts, and updates getUserById, getUserByEmail, and getAccountByUserId to call logError(...) in their catch blocks while still returning null on failure.

Changes

Centralized error logging for user data operations

Layer / File(s) Summary
Redaction and logging implementation
lib/user-data.ts
Introduces SENSITIVE_KEYS, redactParams() (recursive, masks matching keys and objects-in-arrays) and logError() which emits timestamped JSON with function context, redacted params, and error message/stack to console.error.
Query function catch updates
lib/user-data.ts
getUserById, getUserByEmail, and getAccountByUserId now call logError(<fn>, <params>, err) in their catch blocks instead of console.log(err), and continue to return null on error.

Sequence Diagram(s)

sequenceDiagram
  participant getUserFunc as getUserById/getUserByEmail/getAccountByUserId
  participant Redactor as redactParams
  participant Logger as logError
  participant Console as console.error
  getUserFunc->>Redactor: redact input params
  Redactor->>Logger: return redacted params
  getUserFunc->>Logger: call logError(functionName, redactedParams, error)
  Logger->>Console: write JSON log (timestamp, context, params, message/stack)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

🐰
I nibble keys that hide in shade,
I mask the tokens secrets made,
When errors hop across the floor,
I stamp a JSON at the door,
Logs tidy, safe — I bound once more.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description covers key changes and justification but lacks alignment with the provided template structure, missing explicit sections like Type of change, Validation checklist, and Screenshots. Reformat the description to match the repository template with explicit sections: Type of change, Validation steps completed, and the required checklist items.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding PII redaction to error logging in user-data.ts, which is the primary objective of the PR.
Linked Issues check ✅ Passed The PR directly addresses issue #274 by replacing console.log(error) calls with proper redacted error logging via logError() helper in the three specified functions.
Out of Scope Changes check ✅ Passed All changes are focused on redacting PII in error logging and handling per issue #274 requirements. The recursive redaction logic and null-return behavior for DB errors align with the stated objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

👋 Thanks for opening a PR, @narutamaaurum!

Your PR has entered the 🚦 PR Review Pipeline.

Standard PR detected — your PR will follow the standard review pipeline.


What happens next

Stage Reviewer Checks
Stage 1 — Automated Validation 🤖 Bot DCO · Format · AI/Slop · Duplicate
Stage 2 — Human Review 👥 Maintainer Code + Quality Review
Stage 3 — PA / Maintainer Review 🔑 Project Admin Final Merge Decision

A pipeline status comment will appear below and update automatically as your PR progresses.


While you wait

  • Sign all commits (git commit -s)
  • Link your issue (Closes #123)
  • Use a feature branch (not main)
  • Avoid unrelated changes

This comment is posted only once.

@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: 2

🧹 Nitpick comments (1)
lib/user-data.ts (1)

3-4: 💤 Low value

Consider narrowing the "key" pattern to reduce false positives.

The substring "key" will match legitimate non-sensitive fields like primaryKey, foreignKey, cacheKey, indexKey. Consider using more specific patterns like "apikey", "api_key", or "secretkey" instead of the bare "key".

🤖 Prompt for 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.

In `@lib/user-data.ts` around lines 3 - 4, The SENSITIVE_KEYS array currently
includes the overly-broad token "key" which causes false positives; update
SENSITIVE_KEYS (the constant in lib/user-data.ts) to replace "key" with narrower
patterns such as "apikey", "api_key", "secretkey" and optionally "private_key"
or "access_key" so that legitimate fields like primaryKey/foreignKey aren't
matched; ensure any code that uses SENSITIVE_KEYS for detection still works with
the new entries (adjust normalization/lookup if it assumed substring matching).
🤖 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 `@lib/user-data.ts`:
- Around line 5-16: redactParams only inspects top-level keys so nested
objects/arrays with sensitive fields (e.g., user.email) remain unredacted;
update redactParams to perform a recursive traversal: for objects iterate
entries and call the same redaction logic on nested values, for arrays map each
element through the redactor, and when a key (use the lowercased key check
against SENSITIVE_KEYS) matches redact the entire value to "[REDACTED]"; ensure
you return a new structure (do not mutate inputs) and reference the existing
redactParams function and SENSITIVE_KEYS constant when implementing the
recursive helper.
- Around line 40-43: The DB helper functions getUserById, getUserByEmail, and
getAccountByUserId currently log and rethrow errors which causes the auth.ts jwt
callback (which calls getUserById(token.sub) without try/catch) to fail on
transient DB errors; change those functions to catch/log the error and return
null (or undefined) instead of rethrowing so callers like the jwt callback treat
DB failures as “no user” and continue, or alternately add a try/catch around the
getUserById call in the jwt callback to handle errors and degrade to returning
the token; choose one approach and apply consistently to the named
functions/call site so the jwt flow never throws on DB errors.

---

Nitpick comments:
In `@lib/user-data.ts`:
- Around line 3-4: The SENSITIVE_KEYS array currently includes the overly-broad
token "key" which causes false positives; update SENSITIVE_KEYS (the constant in
lib/user-data.ts) to replace "key" with narrower patterns such as "apikey",
"api_key", "secretkey" and optionally "private_key" or "access_key" so that
legitimate fields like primaryKey/foreignKey aren't matched; ensure any code
that uses SENSITIVE_KEYS for detection still works with the new entries (adjust
normalization/lookup if it assumed substring matching).
🪄 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: 34b7708d-20c2-4d9a-851a-925857cdea9f

📥 Commits

Reviewing files that changed from the base of the PR and between f12b223 and 06f9c16.

📒 Files selected for processing (1)
  • lib/user-data.ts

Comment thread lib/user-data.ts
Comment thread lib/user-data.ts
- Narrow SENSITIVE_KEYS: remove overly broad 'key' pattern, add specific patterns (apikey, api_key, secretkey, private_key, access_key)
- Make redactParams recursive to handle nested objects and arrays
- Change DB helper functions (getUserById, getUserByEmail, getAccountByUserId) to return null on error instead of rethrowing, so auth JWT callback treats DB failures as 'no user'

Signed-off-by: Narutama Aurum <narutamaaurum@gmail.com>
@narutamaaurum

Copy link
Copy Markdown
Author

Addressed CodeRabbit review comments:

  1. SENSITIVE_KEYS: Removed overly broad pattern that caused false positives (e.g., , ). Added specific patterns: , , , , .

  2. recursive redactParams: Now recursively traverses nested objects and arrays to redact sensitive keys at any depth.

  3. Error handling: Changed , , and to return on DB errors instead of rethrowing. This allows the auth JWT callback (which calls without try/catch) to gracefully treat DB failures as "no user" rather than crashing.

All lint and tests pass.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/user-data.ts (1)

53-54: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Redact or suppress error text fields before emitting logs.

Line 53 and Line 54 currently log raw error.message/error.stack. Those fields can still contain emails or other identifiers, which bypasses key-based param redaction.

Proposed minimal hardening
+const redactText = (value: string): string =>
+    value
+        // email
+        .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, "[REDACTED_EMAIL]")
+        // broad token-like blobs (JWT/API keys/secrets)
+        .replace(/\b[A-Za-z0-9_-]{20,}\b/g, "[REDACTED_TOKEN]");
+
 const logError = (
     functionName: string,
     params: Record<string, unknown>,
     error: unknown
 ) => {
     console.error(
         JSON.stringify({
             timestamp: new Date().toISOString(),
             level: "error",
             context: functionName,
             params: redactParams(params),
-            error: error instanceof Error ? error.message : "Unknown error",
-            stack: error instanceof Error ? error.stack : undefined,
+            error: error instanceof Error ? redactText(error.message) : "Unknown error",
+            stack: error instanceof Error && error.stack ? redactText(error.stack) : undefined,
         })
     );
 };
🤖 Prompt for 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.

In `@lib/user-data.ts` around lines 53 - 54, The current serialization in
lib/user-data.ts emits raw error.message and error.stack which can leak PII;
replace those with sanitized values before logging by mapping error.message and
error.stack to either a fixed placeholder (e.g. "[REDACTED_ERROR]") or a
redacted string produced by a simple sanitizer that strips emails/identifiers
(apply to the error variable used in the object where error: error instanceof
Error ? error.message : "Unknown error" and stack: error instanceof Error ?
error.stack : undefined). Update the code paths that produce these fields so
logs only contain the sanitized value (or undefined) and ensure the sanitizer is
applied consistently wherever error.message or error.stack are emitted.
🤖 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.

Outside diff comments:
In `@lib/user-data.ts`:
- Around line 53-54: The current serialization in lib/user-data.ts emits raw
error.message and error.stack which can leak PII; replace those with sanitized
values before logging by mapping error.message and error.stack to either a fixed
placeholder (e.g. "[REDACTED_ERROR]") or a redacted string produced by a simple
sanitizer that strips emails/identifiers (apply to the error variable used in
the object where error: error instanceof Error ? error.message : "Unknown error"
and stack: error instanceof Error ? error.stack : undefined). Update the code
paths that produce these fields so logs only contain the sanitized value (or
undefined) and ensure the sanitizer is applied consistently wherever
error.message or error.stack are emitted.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0de5311d-d8b9-47a5-8d50-44cd5e63f89a

📥 Commits

Reviewing files that changed from the base of the PR and between 06f9c16 and b04cea7.

📒 Files selected for processing (1)
  • lib/user-data.ts

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

Labels

good first issue Good for newcomers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove leftover console.log(error) in lib/user-data.ts

1 participant