Files
openclaw/test/scripts/dev-tooling-safety.test.ts
2026-05-17 17:04:18 +08:00

93 lines
3.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { testing as promptProbeTesting } from "../../scripts/anthropic-prompt-probe.ts";
import { testing as claudeUsageTesting } from "../../scripts/debug-claude-usage.ts";
import { testing as discordSmokeTesting } from "../../scripts/dev/discord-acp-plain-language-smoke.ts";
import {
maskIdentifier,
parseBooleanEnv,
parseStrictIntegerOption,
previewForDevToolLog,
redactHomePath,
redactJsonValueForDevToolLog,
} from "../../scripts/lib/dev-tooling-safety.ts";
describe("dev tooling safety helpers", () => {
it("redacts secrets before truncating script log previews", () => {
const token = "sk-test1234567890abcdefghijklmnop"; // pragma: allowlist secret
const preview = previewForDevToolLog(`prefix OPENAI_API_KEY=${token} suffix`, 80);
expect(preview).not.toContain(token);
expect(preview).toContain("OPENAI_API_KEY=");
});
it("recursively redacts JSON-ish detail values before printing smoke results", () => {
const token = "sk-test1234567890abcdefghijklmnop"; // pragma: allowlist secret
const redacted = redactJsonValueForDevToolLog({
nested: [{ message: `Authorization: Bearer ${token}` }],
}) as { nested: Array<{ message: string }> };
expect(redacted.nested[0].message).not.toContain(token);
expect(redacted.nested[0].message).toContain("Authorization");
});
it("parses boolean env values explicitly", () => {
expect(parseBooleanEnv({ fallback: false, name: "FLAG", raw: "yes" })).toBe(true);
expect(parseBooleanEnv({ fallback: true, name: "FLAG", raw: "0" })).toBe(false);
expect(() => parseBooleanEnv({ fallback: false, name: "FLAG", raw: "maybe" })).toThrow(
/FLAG must be one of/u,
);
});
it("rejects partial numeric option parses", () => {
expect(parseStrictIntegerOption({ fallback: 3, label: "--runs", min: 1, raw: undefined })).toBe(
3,
);
expect(() =>
parseStrictIntegerOption({ fallback: 3, label: "--runs", min: 1, raw: "2abc" }),
).toThrow(/--runs must be an integer/u);
});
it("redacts home paths and masks opaque ids", () => {
expect(redactHomePath("/home/alice/.openclaw/state.json", "/home/alice")).toBe(
"~/.openclaw/state.json",
);
expect(maskIdentifier("session-key-abcdef123456")).toBe("sessio...3456");
});
});
describe("script-specific dev tooling hardening", () => {
it("rejects unknown Discord smoke drivers instead of silently using token mode", () => {
expect(discordSmokeTesting.parseDriverMode("webhook")).toBe("webhook");
expect(() => discordSmokeTesting.parseDriverMode("curl")).toThrow(/Invalid --driver/u);
});
it("redacts Discord webhook tokens from API paths", () => {
const token = "webhook-secret-token-abcdef123456"; // pragma: allowlist secret
const path = `/webhooks/123/${token}?wait=true`;
expect(discordSmokeTesting.redactDiscordApiPath(path)).not.toContain(token);
expect(discordSmokeTesting.redactDiscordApiPath(path)).toContain("/webhooks/123/");
});
it("rejects absolute-form URLs in the Anthropic capture proxy", () => {
expect(
promptProbeTesting.resolveAnthropicUpstreamUrl(
"/v1/messages?anthropic-version=2023-06-01",
"https://api.anthropic.com",
),
).toBe("https://api.anthropic.com/v1/messages?anthropic-version=2023-06-01");
expect(() =>
promptProbeTesting.resolveAnthropicUpstreamUrl(
"http://169.254.169.254/latest/meta-data",
"https://api.anthropic.com",
),
).toThrow(/refusing non-origin proxy request URL/u);
});
it("uses exact Claude cookie host matchers instead of broad substring matches", () => {
expect(claudeUsageTesting.CLAUDE_COOKIE_HOST_SQL).toContain("host_key = 'claude.ai'");
expect(claudeUsageTesting.CLAUDE_COOKIE_HOST_SQL).toContain("LIKE '%.claude.ai'");
expect(claudeUsageTesting.CLAUDE_COOKIE_HOST_SQL).not.toContain("%claude.ai%");
});
});