mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 16:45:22 +00:00
112 lines
2.9 KiB
TypeScript
112 lines
2.9 KiB
TypeScript
import { describe, expect, test } from "vitest";
|
|
import {
|
|
isSensitiveLogKey,
|
|
REDACTED_PLACEHOLDER,
|
|
redactedJsonStringify,
|
|
} from "#src/log-redaction";
|
|
|
|
describe("isSensitiveLogKey", () => {
|
|
test.each([
|
|
"authorization",
|
|
"Authorization",
|
|
"apiKey",
|
|
"api_key",
|
|
"api-key",
|
|
"x-api-key",
|
|
"ANTHROPIC_API_KEY",
|
|
"secret",
|
|
"clientSecret",
|
|
"token",
|
|
"accessToken",
|
|
"refresh_token",
|
|
"password",
|
|
"passwd",
|
|
"credential",
|
|
"credentials",
|
|
"cookie",
|
|
"privateKey",
|
|
"private_key",
|
|
])("treats %s as sensitive", (key) => {
|
|
expect(isSensitiveLogKey(key)).toBe(true);
|
|
});
|
|
|
|
test.each([
|
|
"toolName",
|
|
"command",
|
|
"path",
|
|
"target",
|
|
"origin",
|
|
"matchedPattern",
|
|
"resolution",
|
|
"toolInputPreview",
|
|
"requesterAgentName",
|
|
"denialReason",
|
|
"",
|
|
])("treats %s as not sensitive", (key) => {
|
|
expect(isSensitiveLogKey(key)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("redactedJsonStringify", () => {
|
|
test("masks a top-level sensitive value", () => {
|
|
expect(redactedJsonStringify({ token: "abc123" })).toBe(
|
|
`{"token":"${REDACTED_PLACEHOLDER}"}`,
|
|
);
|
|
});
|
|
|
|
test("masks a nested sensitive value", () => {
|
|
const details = {
|
|
toolName: "http",
|
|
headers: { authorization: "Bearer TEST_VALUE" },
|
|
};
|
|
|
|
expect(redactedJsonStringify(details)).toBe(
|
|
`{"toolName":"http","headers":{"authorization":"${REDACTED_PLACEHOLDER}"}}`,
|
|
);
|
|
});
|
|
|
|
test("masks a sensitive value inside an array element", () => {
|
|
const details = { entries: [{ name: "prod", apiKey: "sk-real-value" }] };
|
|
|
|
expect(redactedJsonStringify(details)).toBe(
|
|
`{"entries":[{"name":"prod","apiKey":"${REDACTED_PLACEHOLDER}"}]}`,
|
|
);
|
|
});
|
|
|
|
test("masks an object-valued sensitive key without descending into it", () => {
|
|
const details = { credentials: { user: "root", password: "hunter2" } };
|
|
|
|
expect(redactedJsonStringify(details)).toBe(
|
|
`{"credentials":"${REDACTED_PLACEHOLDER}"}`,
|
|
);
|
|
});
|
|
|
|
test("leaves non-sensitive keys untouched", () => {
|
|
const details = {
|
|
toolName: "bash",
|
|
command: "echo hello",
|
|
matchedPattern: "echo *",
|
|
};
|
|
|
|
expect(redactedJsonStringify(details)).toBe(
|
|
'{"toolName":"bash","command":"echo hello","matchedPattern":"echo *"}',
|
|
);
|
|
});
|
|
|
|
test("leaves a null or absent sensitive value as-is rather than reading as suppressed", () => {
|
|
expect(redactedJsonStringify({ token: null })).toBe('{"token":null}');
|
|
expect(redactedJsonStringify({ token: undefined })).toBe("{}");
|
|
});
|
|
|
|
test("retains the Error, bigint, and cycle handling of the plain serializer", () => {
|
|
const error = new Error("boom");
|
|
error.stack = "trace";
|
|
const node: Record<string, unknown> = { size: 10n, error };
|
|
node.self = node;
|
|
|
|
expect(redactedJsonStringify(node)).toBe(
|
|
'{"size":"10","error":{"name":"Error","message":"boom","stack":"trace"},"self":"[Circular]"}',
|
|
);
|
|
});
|
|
});
|