os.homedir() returns backslashes on Windows but Claude Code outputs paths with forward slashes. Replace both C:\Users\x and C:/Users/x variants so home and repoRoot are always redacted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
export interface SanitizeOptions {
|
|
repoRoot?: string; // e.g. /home/user/.disclaw
|
|
home?: string; // os.homedir()
|
|
}
|
|
|
|
/**
|
|
* Sanitizes agent output before it is sent to a Discord channel.
|
|
* Replaces absolute paths and sensitive tokens so they are never leaked.
|
|
*
|
|
* Replacement order is intentional — longest/most-specific patterns first:
|
|
* 1. repoRoot → <disclaw>
|
|
* 2. home → ~
|
|
* 3. Discord bot token pattern → <redacted>
|
|
* 4. Anthropic API key pattern → <redacted>
|
|
*/
|
|
/** Returns both backslash and forward-slash variants of a path (for Windows). */
|
|
function pathVariants(p: string): string[] {
|
|
const fwd = p.replace(/\\/g, "/");
|
|
const bwd = p.replace(/\//g, "\\");
|
|
return fwd === bwd ? [p] : [p, fwd, bwd];
|
|
}
|
|
|
|
function replaceAll(text: string, search: string, replacement: string): string {
|
|
return text.split(search).join(replacement);
|
|
}
|
|
|
|
export function sanitizeForDiscord(
|
|
text: string,
|
|
opts: SanitizeOptions = {}
|
|
): string {
|
|
let result = text;
|
|
|
|
// 1. Replace repo root before home so that sub-paths are caught by the
|
|
// more specific substitution first (repoRoot is usually inside home).
|
|
if (opts.repoRoot) {
|
|
for (const variant of pathVariants(opts.repoRoot)) {
|
|
result = replaceAll(result, variant, "<disclaw>");
|
|
}
|
|
}
|
|
|
|
// 2. Replace home directory with ~ (both slash styles for Windows)
|
|
if (opts.home) {
|
|
for (const variant of pathVariants(opts.home)) {
|
|
result = replaceAll(result, variant, "~");
|
|
}
|
|
}
|
|
|
|
// 3. Discord bot token — format: [MN]<23 base64url>.<6 base64url>.<27 base64url>
|
|
result = result.replace(
|
|
/[MN][A-Za-z\d]{23}\.[\w-]{6}\.[\w-]{27}/g,
|
|
"<redacted>"
|
|
);
|
|
|
|
// 4. Anthropic API key — format: sk-ant-<20+ base64url chars>
|
|
result = result.replace(/sk-ant-[A-Za-z0-9\-_]{20,}/g, "<redacted>");
|
|
|
|
return result;
|
|
}
|