The root cause was twofold: 1. Raw (unsanitized) agent responses were stored in the conversation history DB. On subsequent calls, these paths were fed back to the agent as context, causing it to reproduce full paths regardless of Discord-side sanitization. 2. repoRoot (workspace_path) was not passed to sanitizeForDiscord, so workspace-specific paths were only partially masked via the home directory fallback. Fix: sanitize the full response once before both sending to Discord and storing in the DB. Pass workspace_path as repoRoot for precise path replacement. Add Windows path tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
87 lines
3.7 KiB
TypeScript
87 lines
3.7 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { sanitizeForDiscord } from "../../src/runtime/sanitize";
|
|
|
|
describe("sanitizeForDiscord", () => {
|
|
// (a) Repo-root path is replaced with <disclaw>
|
|
it("replaces repoRoot with <disclaw>", () => {
|
|
const text = "Reading config from /home/user/project/disclaw.yaml";
|
|
const result = sanitizeForDiscord(text, { repoRoot: "/home/user/project" });
|
|
expect(result).toBe("Reading config from <disclaw>/disclaw.yaml");
|
|
expect(result).not.toContain("/home/user/project");
|
|
});
|
|
|
|
// (b) Home directory is replaced with ~
|
|
it("replaces home directory with ~", () => {
|
|
const text = "Workspace located at /home/user/.disclaw/workspaces/agent-x";
|
|
const result = sanitizeForDiscord(text, { home: "/home/user" });
|
|
expect(result).toBe("Workspace located at ~/.disclaw/workspaces/agent-x");
|
|
expect(result).not.toContain("/home/user");
|
|
});
|
|
|
|
// (c) Discord bot token pattern is redacted
|
|
it("redacts Discord bot tokens", () => {
|
|
const token = "MTA1NjYwNDczNTA3NDU2NjE2.GbXkRa.abcdefghijklmnopqrstuvwxyz123";
|
|
const text = `Bot initialized with token ${token} — ready.`;
|
|
const result = sanitizeForDiscord(text);
|
|
expect(result).not.toContain(token);
|
|
expect(result).toContain("<redacted>");
|
|
});
|
|
|
|
// (d) Anthropic API key is redacted
|
|
it("redacts Anthropic API keys", () => {
|
|
const key = "sk-ant-api03-ABCDEFGHIJ1234567890abcdefghij";
|
|
const text = `Using key ${key} for requests.`;
|
|
const result = sanitizeForDiscord(text);
|
|
expect(result).not.toContain(key);
|
|
expect(result).toContain("<redacted>");
|
|
});
|
|
|
|
// (e) Harmless text is not modified (no false positives)
|
|
it("does not modify harmless text", () => {
|
|
const text = "Hello! The agent processed your request successfully in 120ms.";
|
|
const result = sanitizeForDiscord(text, { home: "/home/user", repoRoot: "/home/user/project" });
|
|
expect(result).toBe(text);
|
|
});
|
|
|
|
// (f) Empty string returns empty string
|
|
it("handles empty string input", () => {
|
|
expect(sanitizeForDiscord("")).toBe("");
|
|
expect(sanitizeForDiscord("", { home: "/home/user", repoRoot: "/home/user/project" })).toBe("");
|
|
});
|
|
|
|
// (g) No opts provided — plain text stays unchanged when no token patterns present
|
|
it("returns text unchanged when no opts and no token patterns", () => {
|
|
const text = "This is a perfectly normal response from the agent.";
|
|
expect(sanitizeForDiscord(text)).toBe(text);
|
|
});
|
|
|
|
// Ordering: repoRoot (sub-path of home) is replaced before home
|
|
it("replaces repoRoot before home so nested paths are handled correctly", () => {
|
|
const text = "/home/user/project/src/index.ts and /home/user/other.ts";
|
|
const result = sanitizeForDiscord(text, {
|
|
repoRoot: "/home/user/project",
|
|
home: "/home/user",
|
|
});
|
|
expect(result).toBe("<disclaw>/src/index.ts and ~/other.ts");
|
|
});
|
|
|
|
// Windows-style backslash paths are sanitized
|
|
it("replaces Windows backslash paths", () => {
|
|
const text = "File at C:\\Users\\dev\\.disclaw\\workspaces\\agent-x\\src\\main.ts";
|
|
const result = sanitizeForDiscord(text, {
|
|
repoRoot: "C:\\Users\\dev\\.disclaw\\workspaces\\agent-x",
|
|
home: "C:\\Users\\dev",
|
|
});
|
|
expect(result).toBe("File at <disclaw>\\src\\main.ts");
|
|
});
|
|
|
|
// Mixed slash styles (common on Windows when tools output forward slashes)
|
|
it("replaces forward-slash variants of Windows paths", () => {
|
|
const text = "File at C:/Users/dev/.disclaw/workspaces/agent-x/src/main.ts";
|
|
const result = sanitizeForDiscord(text, {
|
|
repoRoot: "C:\\Users\\dev\\.disclaw\\workspaces\\agent-x",
|
|
home: "C:\\Users\\dev",
|
|
});
|
|
expect(result).toBe("File at <disclaw>/src/main.ts");
|
|
});
|
|
});
|