mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-08-22 03:18:54 +08:00
fix(security): unify secret redaction in public comment outputs (#1693)
Ensure all public issue, PR, and inline comments apply redactSecrets() in addition to sanitizeContent() before submitting payloads to the GitHub API. This aligns public comment output with error log and step-summary redaction policies, preventing potential leakage of Anthropic API keys, AWS credentials, Slack tokens, JWTs, and GitHub tokens.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import { redactSecrets, sanitizeContent } from "../src/github/utils/sanitizer";
|
||||
|
||||
describe("Public Comment Output Sanitization & Redaction", () => {
|
||||
it("redacts all credential types from public comment output", () => {
|
||||
const rawComment = [
|
||||
"Here is the summary of the work done:",
|
||||
"- GitHub Token: ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
|
||||
"- Anthropic Key: sk-ant-api03-abcdefghijklmnopqrstuvwxyz1234567890",
|
||||
"- AWS Access Key: AKIAIOSFODNN7EXAMPLE",
|
||||
"- Slack Bot Token: xoxb-1234567890-abcdefghijkl-mnopqrstuvwx",
|
||||
"- JWT Bearer: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
|
||||
"<!-- Hidden instruction injection -->",
|
||||
"Invisible\u200Bzero-width chars",
|
||||
"",
|
||||
].join("\n");
|
||||
|
||||
const sanitizedOutput = redactSecrets(sanitizeContent(rawComment));
|
||||
|
||||
// Ensure all secret types are redacted
|
||||
expect(sanitizedOutput).not.toContain(
|
||||
"ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
|
||||
);
|
||||
expect(sanitizedOutput).not.toContain(
|
||||
"sk-ant-api03-abcdefghijklmnopqrstuvwxyz1234567890",
|
||||
);
|
||||
expect(sanitizedOutput).not.toContain("AKIAIOSFODNN7EXAMPLE");
|
||||
expect(sanitizedOutput).not.toContain(
|
||||
"xoxb-1234567890-abcdefghijkl-mnopqrstuvwx",
|
||||
);
|
||||
expect(sanitizedOutput).not.toContain(
|
||||
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
|
||||
);
|
||||
|
||||
expect(sanitizedOutput).toContain("[REDACTED_GITHUB_TOKEN]");
|
||||
expect(sanitizedOutput).toContain("[REDACTED_ANTHROPIC_KEY]");
|
||||
expect(sanitizedOutput).toContain("[REDACTED_AWS_KEY_ID]");
|
||||
expect(sanitizedOutput).toContain("[REDACTED_SLACK_TOKEN]");
|
||||
expect(sanitizedOutput).toContain("[REDACTED_JWT]");
|
||||
|
||||
// Ensure prompt injection / invisible chars / hidden tags are also sanitized
|
||||
expect(sanitizedOutput).not.toContain(
|
||||
"<!-- Hidden instruction injection -->",
|
||||
);
|
||||
expect(sanitizedOutput).not.toContain("\u200B");
|
||||
expect(sanitizedOutput).not.toContain("Image Alt Injection");
|
||||
expect(sanitizedOutput).toContain("");
|
||||
});
|
||||
|
||||
it("ensures public comments have the same secret redaction coverage as logs/errors", () => {
|
||||
const errorDetails =
|
||||
"Error: failed to connect with sk-ant-abcdefghijklmnopqrstuvwxyz123456 and AKIAIOSFODNN7EXAMPLE";
|
||||
const commentBody =
|
||||
"Report: encountered sk-ant-abcdefghijklmnopqrstuvwxyz123456 and AKIAIOSFODNN7EXAMPLE";
|
||||
|
||||
const redactedError = redactSecrets(errorDetails);
|
||||
const redactedComment = redactSecrets(sanitizeContent(commentBody));
|
||||
|
||||
expect(redactedError).toContain("[REDACTED_ANTHROPIC_KEY]");
|
||||
expect(redactedError).toContain("[REDACTED_AWS_KEY_ID]");
|
||||
expect(redactedComment).toContain("[REDACTED_ANTHROPIC_KEY]");
|
||||
expect(redactedComment).toContain("[REDACTED_AWS_KEY_ID]");
|
||||
});
|
||||
});
|
||||
@@ -518,3 +518,28 @@ describe("stripHtmlComments (legacy)", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("outbound comment sanitization and redaction", () => {
|
||||
it("should sanitize content and redact all credential types for public comments", () => {
|
||||
const rawComment =
|
||||
"Done! Configured AWS AKIAIOSFODNN7EXAMPLE, Anthropic sk-ant-api03-abcdefghijklmnopqrstuvwxyz1234567890, Slack xoxb-1234567890-abcdefghijkl-mnopqrstuvwx, and GitHub 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 <!-- secret note -->";
|
||||
const sanitizedAndRedacted = redactSecrets(sanitizeContent(rawComment));
|
||||
|
||||
expect(sanitizedAndRedacted).not.toContain("AKIAIOSFODNN7EXAMPLE");
|
||||
expect(sanitizedAndRedacted).not.toContain(
|
||||
"sk-ant-api03-abcdefghijklmnopqrstuvwxyz1234567890",
|
||||
);
|
||||
expect(sanitizedAndRedacted).not.toContain(
|
||||
"xoxb-1234567890-abcdefghijkl-mnopqrstuvwx",
|
||||
);
|
||||
expect(sanitizedAndRedacted).not.toContain(
|
||||
"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",
|
||||
);
|
||||
expect(sanitizedAndRedacted).not.toContain("secret note");
|
||||
|
||||
expect(sanitizedAndRedacted).toContain("[REDACTED_AWS_KEY_ID]");
|
||||
expect(sanitizedAndRedacted).toContain("[REDACTED_ANTHROPIC_KEY]");
|
||||
expect(sanitizedAndRedacted).toContain("[REDACTED_SLACK_TOKEN]");
|
||||
expect(sanitizedAndRedacted).toContain("[REDACTED_GITHUB_TOKEN]");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user