-
-
Notifications
You must be signed in to change notification settings - Fork 477
Redact secrets from command previews #288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import assert from "node:assert/strict"; | ||
| import test from "node:test"; | ||
| import { commandPreview } from "./logger.js"; | ||
|
|
||
| test("command previews redact common secret forms while preserving useful context", () => { | ||
| const preview = commandPreview( | ||
| "deploy --token abc123 --password=hidden API_KEY=key123 -authorization BearerToken curl -H 'Authorization: Bearer xyz789'", | ||
| ); | ||
|
|
||
| assert.match(preview, /deploy/); | ||
| assert.match(preview, /--token \[REDACTED\]/); | ||
| assert.match(preview, /--password=\[REDACTED\]/); | ||
| assert.match(preview, /API_KEY=\[REDACTED\]/); | ||
| assert.doesNotMatch(preview, /abc123|hidden|key123|xyz789/); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -74,7 +74,11 @@ export function sessionIdPrefix(sessionId: string | undefined): string | undefin | |
|
|
||
| export function commandPreview(command: string): string { | ||
| const normalized = command.replace(/\s+/g, " ").trim(); | ||
| return normalized.length > 120 ? `${normalized.slice(0, 117)}...` : normalized; | ||
| const redacted = normalized | ||
| .replace(/((?:--?|\/)(?:token|password|secret|api[-_]?key|authorization)(?:=|\s+))["']?[^\s"']+["']?/giu, "$1[REDACTED]") | ||
| .replace(/\b((?:token|password|secret|api[-_]?key|authorization)\s*=\s*)["']?[^\s"']+["']?/giu, "$1[REDACTED]") | ||
|
Comment on lines
+78
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a shell command contains a quoted multi-word credential such as How this was verified: The optional opening quote is followed by
Comment on lines
+78
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Preserve context after assignment redaction. The assignment patterns treat 🤖 Prompt for AI Agents🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Sensitive Data Exposure (CWE-532): Insertion of Sensitive Information into Log File Consume complete quoted credential values. Quoted values are truncated at the first space, leaving credential suffixes in 🤖 Prompt for AI Agents |
||
| .replace(/\b(Bearer\s+)[A-Za-z0-9._~+\/-]+=*/giu, "$1[REDACTED]"); | ||
| return redacted.length > 120 ? `${redacted.slice(0, 117)}...` : redacted; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a long recognized credential precedes an unrecognized credential such as How this was verified: The changed flow replaces long recognized values before calculating the preview slice, while cookie and session forms remain outside the redaction patterns. |
||
| } | ||
|
|
||
| function firstHeaderValue(value: string | undefined): string | undefined { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Assert the authorization-flag redaction.
The fixture includes
-authorization BearerToken, but the test neither checks for-authorization [REDACTED]nor rejectsBearerToken. A regression in this redaction path would still pass.Suggested assertion update
📝 Committable suggestion
🤖 Prompt for AI Agents