fix(security): redact secret patterns from CLI log and error output#672
fix(security): redact secret patterns from CLI log and error output#672WuKongAI-CMU wants to merge 2 commits intoNVIDIA:mainfrom
Conversation
Add a redact() helper to bin/lib/runner.js that masks known secret patterns before they reach CLI error messages. Covers: - NVIDIA API keys (nvapi-*) - NVCF keys (nvcf-*) - Bearer tokens - Generic key/token/password assignments Applied to all run() and runInteractive() error output where the failing command string is logged. Non-secret strings pass through unchanged. Fixes NVIDIA#664 Signed-off-by: peteryuqin <peter.yuqin@gmail.com>
📝 WalkthroughWalkthroughThis PR adds a secret redaction utility to prevent API keys and tokens from leaking in CLI error output. A Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 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. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
bin/lib/runner.js (1)
46-58:⚠️ Potential issue | 🟡 MinorApply
redact()torunCaptureerror paths for consistency with other run functions.
runCapturethrows unredacted exceptions (line 57), whilerun()andrunInteractive()both applyredact()to command failures. This inconsistency creates a defensive programming gap: although current callers catch errors without logging, future modifications could expose the unredacted command string containing secrets. Align with the existing pattern by wrapping the thrown error message withredact().🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/runner.js` around lines 46 - 58, The catch block in runCapture currently rethrows the raw error; update runCapture so that in the catch, after handling opts.ignoreError, it rethrows the error wrapped with redact() (i.e., throw redact(err)) to match the behavior of run() and runInteractive(); keep the existing ignoreError return "" behavior and ensure you reference the runCapture function and redact() wrapper when making the change.
🧹 Nitpick comments (2)
test/runner.test.js (1)
144-182: Consider adding test cases for edge patterns and potential bypasses.The test suite covers the happy paths well. Consider adding tests for:
- Case sensitivity: Does
BEARER(uppercase) orbearer(lowercase) get masked? (The regex usesgiflag, so it should)- Quoted values:
API_KEY="secret123abc"— does the quote handling work?- Multiple secrets in one string:
nvapi-key1 nvapi-key2Optional: Additional test cases
it("masks bearer tokens case-insensitively", () => { const { redact } = require(runnerPath); expect(redact("authorization: bearer someToken1234")).toContain("****"); }); it("masks multiple secrets in one string", () => { const { redact } = require(runnerPath); const input = "nvapi-firstkey12345 and nvapi-secondkey6789"; const output = redact(input); expect(output).not.toContain("firstkey"); expect(output).not.toContain("secondkey"); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/runner.test.js` around lines 144 - 182, Add unit tests to cover edge patterns and potential bypasses for the redact function: include case-insensitive bearer variations (e.g., "BEARER"/"bearer") to ensure redact (from runnerPath) handles regex flags correctly, add quoted assignment cases (e.g., API_KEY="secret123abc") to verify quotes are masked, and add a test with multiple secrets in one string (e.g., "nvapi-first nvapi-second") to confirm redact masks all occurrences; place these new it() cases alongside the existing describe("redact") block referencing redact from runnerPath.bin/lib/runner.js (1)
66-71: Add coverage for_KEY=andghp_patterns to match shell script.The JS patterns miss two variants that are covered in
scripts/debug.sh(lines 107-113):
ghp_prefix (GitHub personal access tokens)_KEY=suffix (catchesNVIDIA_API_KEY,OTHER_API_KEY, etc.)The shell script redacts both, but the JS version only covers
API_KEY,SECRET,TOKEN,PASSWORD,CREDENTIAL.Suggested update
const SECRET_PATTERNS = [ /nvapi-[A-Za-z0-9_-]{10,}/g, /nvcf-[A-Za-z0-9_-]{10,}/g, + /ghp_[A-Za-z0-9]{30,}/g, /(?<=Bearer\s)[A-Za-z0-9_.+/=-]{10,}/gi, - /(?<=(?:API_KEY|SECRET|TOKEN|PASSWORD|CREDENTIAL)[=: ]['"]?)[A-Za-z0-9_.+/=-]{10,}/gi, + /(?<=(?:_KEY|API_KEY|SECRET|TOKEN|PASSWORD|CREDENTIAL)[=: ]['"]?)[A-Za-z0-9_.+/=-]{10,}/gi, ];🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/lib/runner.js` around lines 66 - 71, SECRET_PATTERNS in runner.js is missing coverage for GitHub PATs and env vars that end with _KEY; update the SECRET_PATTERNS array (the constant named SECRET_PATTERNS) to add a regex for the ghp_ prefix (e.g. match ghp_[A-Za-z0-9_-]{10,}) and extend the existing lookbehind group that matches API_KEY/SECRET/TOKEN/PASSWORD/CREDENTIAL to also accept variable names that end with _KEY (so include _KEY in that lookbehind), keeping the same overall length threshold and flags as the other patterns.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@bin/lib/runner.js`:
- Around line 46-58: The catch block in runCapture currently rethrows the raw
error; update runCapture so that in the catch, after handling opts.ignoreError,
it rethrows the error wrapped with redact() (i.e., throw redact(err)) to match
the behavior of run() and runInteractive(); keep the existing ignoreError return
"" behavior and ensure you reference the runCapture function and redact()
wrapper when making the change.
---
Nitpick comments:
In `@bin/lib/runner.js`:
- Around line 66-71: SECRET_PATTERNS in runner.js is missing coverage for GitHub
PATs and env vars that end with _KEY; update the SECRET_PATTERNS array (the
constant named SECRET_PATTERNS) to add a regex for the ghp_ prefix (e.g. match
ghp_[A-Za-z0-9_-]{10,}) and extend the existing lookbehind group that matches
API_KEY/SECRET/TOKEN/PASSWORD/CREDENTIAL to also accept variable names that end
with _KEY (so include _KEY in that lookbehind), keeping the same overall length
threshold and flags as the other patterns.
In `@test/runner.test.js`:
- Around line 144-182: Add unit tests to cover edge patterns and potential
bypasses for the redact function: include case-insensitive bearer variations
(e.g., "BEARER"/"bearer") to ensure redact (from runnerPath) handles regex flags
correctly, add quoted assignment cases (e.g., API_KEY="secret123abc") to verify
quotes are masked, and add a test with multiple secrets in one string (e.g.,
"nvapi-first nvapi-second") to confirm redact masks all occurrences; place these
new it() cases alongside the existing describe("redact") block referencing
redact from runnerPath.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 29d3d3d1-7a52-4a7e-a4ec-c0af1bf967dd
📒 Files selected for processing (2)
bin/lib/runner.jstest/runner.test.js
|
Pushed a follow-up in |
Summary
Adds a
redact()helper tobin/lib/runner.jsthat masks known secret patterns before they reach CLI error messages.Patterns covered:
nvapi-*)nvcf-*)Applied to all
run()andrunInteractive()error output where the failing command string is logged. Non-secret strings pass through unchanged.Test plan
test/runner.test.jscovering all pattern types + non-secret passthrough + non-string inputFixes #664
Summary by CodeRabbit
Bug Fixes
Tests