(text: string)
| 60 | * Sanitize user input before passing to Claude |
| 61 | */ |
| 62 | export function sanitizeInput(text: string): SanitizationResult { |
| 63 | let sanitized = text; |
| 64 | let flagged = false; |
| 65 | let reason: string | undefined; |
| 66 | |
| 67 | // Check for suspicious patterns |
| 68 | for (const pattern of SUSPICIOUS_PATTERNS) { |
| 69 | if (pattern.test(text)) { |
| 70 | flagged = true; |
| 71 | reason = `Suspicious pattern detected`; |
| 72 | logger.warn({ pattern: pattern.source.substring(0, 50) }, 'Addie: Suspicious input pattern'); |
| 73 | break; |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | // Remove potential delimiter injection |
| 78 | sanitized = sanitized |
| 79 | .replace(/\[system\]/gi, '[sys tem]') |
| 80 | .replace(/\[user\]/gi, '[us er]') |
| 81 | .replace(/\[assistant\]/gi, '[assis tant]'); |
| 82 | |
| 83 | // Limit message length to prevent context stuffing |
| 84 | const MAX_LENGTH = 4000; |
| 85 | if (sanitized.length > MAX_LENGTH) { |
| 86 | sanitized = sanitized.substring(0, MAX_LENGTH) + '... [truncated]'; |
| 87 | if (!flagged) { |
| 88 | flagged = true; |
| 89 | reason = 'Message truncated due to excessive length'; |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | return { |
| 94 | valid: true, |
| 95 | sanitized, |
| 96 | flagged, |
| 97 | reason, |
| 98 | }; |
| 99 | } |
| 100 | |
| 101 | /** |
| 102 | * Convert markdown links to Slack mrkdwn format. |
no test coverage detected