This commit is contained in:
km-anthropic
2025-08-18 17:10:03 -07:00
14 changed files with 293 additions and 34 deletions

View File

@@ -7,6 +7,7 @@ import {
normalizeHtmlEntities,
sanitizeContent,
stripHtmlComments,
redactGitHubTokens,
} from "../src/github/utils/sanitizer";
describe("stripInvisibleCharacters", () => {
@@ -242,6 +243,109 @@ describe("sanitizeContent", () => {
});
});
describe("redactGitHubTokens", () => {
it("should redact personal access tokens (ghp_)", () => {
const token = "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";
expect(redactGitHubTokens(`Token: ${token}`)).toBe(
"Token: [REDACTED_GITHUB_TOKEN]",
);
expect(redactGitHubTokens(`Here's a token: ${token} in text`)).toBe(
"Here's a token: [REDACTED_GITHUB_TOKEN] in text",
);
});
it("should redact OAuth tokens (gho_)", () => {
const token = "gho_16C7e42F292c6912E7710c838347Ae178B4a";
expect(redactGitHubTokens(`OAuth: ${token}`)).toBe(
"OAuth: [REDACTED_GITHUB_TOKEN]",
);
});
it("should redact installation tokens (ghs_)", () => {
const token = "ghs_xz7yzju2SZjGPa0dUNMAx0SH4xDOCS31LXQW";
expect(redactGitHubTokens(`Install token: ${token}`)).toBe(
"Install token: [REDACTED_GITHUB_TOKEN]",
);
});
it("should redact refresh tokens (ghr_)", () => {
const token = "ghr_1B4a2e77838347a253e56d7b5253e7d11667";
expect(redactGitHubTokens(`Refresh: ${token}`)).toBe(
"Refresh: [REDACTED_GITHUB_TOKEN]",
);
});
it("should redact fine-grained tokens (github_pat_)", () => {
const token =
"github_pat_11ABCDEFG0example5of9_2nVwvsylpmOLboQwTPTLewDcE621dQ0AAaBBCCDDEEFFHH";
expect(redactGitHubTokens(`Fine-grained: ${token}`)).toBe(
"Fine-grained: [REDACTED_GITHUB_TOKEN]",
);
});
it("should handle tokens in code blocks", () => {
const content = `\`\`\`bash
export GITHUB_TOKEN=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
\`\`\``;
const expected = `\`\`\`bash
export GITHUB_TOKEN=[REDACTED_GITHUB_TOKEN]
\`\`\``;
expect(redactGitHubTokens(content)).toBe(expected);
});
it("should handle multiple tokens in one text", () => {
const content =
"Token 1: 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 and token 2: gho_16C7e42F292c6912E7710c838347Ae178B4a";
expect(redactGitHubTokens(content)).toBe(
"Token 1: [REDACTED_GITHUB_TOKEN] and token 2: [REDACTED_GITHUB_TOKEN]",
);
});
it("should handle tokens in URLs", () => {
const content =
"https://api.github.com/user?access_token=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";
expect(redactGitHubTokens(content)).toBe(
"https://api.github.com/user?access_token=[REDACTED_GITHUB_TOKEN]",
);
});
it("should not redact partial matches or invalid tokens", () => {
const content =
"This is not a token: ghp_short or gho_toolong1234567890123456789012345678901234567890";
expect(redactGitHubTokens(content)).toBe(content);
});
it("should preserve normal text", () => {
const content = "Normal text with no tokens";
expect(redactGitHubTokens(content)).toBe(content);
});
it("should handle edge cases", () => {
expect(redactGitHubTokens("")).toBe("");
expect(redactGitHubTokens("ghp_")).toBe("ghp_");
expect(redactGitHubTokens("github_pat_short")).toBe("github_pat_short");
});
});
describe("sanitizeContent with token redaction", () => {
it("should redact tokens as part of full sanitization", () => {
const content = `
<!-- Hidden comment with token: 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 -->
Here's some text with a token: gho_16C7e42F292c6912E7710c838347Ae178B4a
And invisible chars: test\u200Btoken
`;
const sanitized = sanitizeContent(content);
expect(sanitized).not.toContain("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");
expect(sanitized).not.toContain("gho_16C7e42F292c6912E7710c838347Ae178B4a");
expect(sanitized).not.toContain("<!-- Hidden comment");
expect(sanitized).not.toContain("\u200B");
expect(sanitized).toContain("[REDACTED_GITHUB_TOKEN]");
expect(sanitized).toContain("Here's some text with a token:");
});
});
describe("stripHtmlComments (legacy)", () => {
it("should remove HTML comments", () => {
expect(stripHtmlComments("Hello <!-- example -->World")).toBe(