// 疑似金鑰:寫入互動記憶與注入內容前一律過濾 const PATTERNS: RegExp[] = [ /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g, /\bsk-[A-Za-z0-9_-]{16,}/g, /\b(?:ghp|gho|ghu|ghs|ghr|glpat|xox[baprs])[-_][A-Za-z0-9_-]{10,}/g, /\bAKIA[0-9A-Z]{16}\b/g, /\bBearer\s+[A-Za-z0-9._~+/=-]{16,}/gi, /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g, /\b(?:api[_-]?key|secret|token|passwd|password|pwd)\s*[:=]\s*\S{6,}/gi, /\b[A-Za-z0-9+/_-]{32,}={0,2}(?![A-Za-z0-9])/g, ] export const REDACTED = '[已遮蔽]' export function redactSecrets(text: string): string { return PATTERNS.reduce((s, re) => s.replace(re, REDACTED), text) } export function hasSecret(text: string): boolean { return redactSecrets(text) !== text }