Spaces:
Paused
Paused
| /** | |
| * Input Sanitization Utilities | |
| * Protects against XSS, prompt injection, and other injection attacks | |
| */ | |
| import createDOMPurify from 'dompurify' | |
| import {JSDOM} from 'jsdom' | |
| const window = new JSDOM('').window | |
| const DOMPurify = createDOMPurify(window as any) | |
| // DOMPurify config for strict sanitization | |
| const PURIFY_CONFIG = { | |
| ALLOWED_TAGS: [], // No HTML tags allowed | |
| ALLOWED_ATTR: [], // No attributes allowed | |
| KEEP_CONTENT: true // Keep text content | |
| } | |
| /** | |
| * Sanitize user input to remove HTML/JS | |
| * Use for: Issue comments, PR descriptions, user-generated content | |
| */ | |
| export const sanitizeHTML = (input: string): string => { | |
| if (!input) return '' | |
| return DOMPurify.sanitize(input, PURIFY_CONFIG) | |
| } | |
| /** | |
| * Escape special regex characters | |
| * Use for: Preventing regex injection | |
| */ | |
| export const escapeRegex = (input: string): string => { | |
| return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') | |
| } | |
| /** | |
| * Escape shell command arguments | |
| * Use for: Preventing command injection in exec calls | |
| */ | |
| export const escapeShellArg = (arg: string): string => { | |
| // Remove null bytes and escape quotes | |
| return arg.replace(/\x00/g, '').replace(/["'`]/g, '') | |
| } | |
| /** | |
| * Sanitize AI prompt input | |
| * Prevents prompt injection attacks | |
| */ | |
| export const sanitizePrompt = (input: string): string => { | |
| if (!input) return '' | |
| // Remove common prompt injection patterns | |
| const dangerousPatterns = [ | |
| /ignore previous instructions/gi, | |
| /disregard (the|all|any) (above|previous|prior)/gi, | |
| /system prompt/gi, | |
| /you are now/gi, | |
| /new instructions/gi, | |
| /===END.*===/gi, // Pattern markers | |
| /<\|endoftext\|>/gi, // GPT end markers | |
| /\[SYSTEM\]/gi, | |
| /\[INSTRUCTION\]/gi, | |
| /\[PROMPT\]/gi | |
| ] | |
| let sanitized = input | |
| for (const pattern of dangerousPatterns) { | |
| sanitized = sanitized.replace(pattern, '[REDACTED]') | |
| } | |
| // Also apply HTML sanitization | |
| return sanitizeHTML(sanitized) | |
| } | |
| /** | |
| * Sanitize filename/path input | |
| * Prevents path traversal attacks | |
| */ | |
| export const sanitizePath = (input: string): string => { | |
| if (!input) return '' | |
| // Remove path traversal patterns | |
| return input | |
| .replace(/\.\./g, '') // Remove parent directory references | |
| .replace(/^[\/\\]/, '') // Remove leading slashes | |
| .replace(/\x00/g, '') // Remove null bytes | |
| } | |
| /** | |
| * Validate and sanitize webhook payload | |
| */ | |
| export const sanitizeWebhookPayload = (payload: any): any => { | |
| if (typeof payload !== 'object' || payload === null) { | |
| return payload | |
| } | |
| const sanitized: any = {} | |
| for (const [key, value] of Object.entries(payload)) { | |
| if (typeof value === 'string') { | |
| // Sanitize string values | |
| sanitized[key] = sanitizeHTML(value) | |
| } else if (typeof value === 'object' && value !== null) { | |
| // Recursively sanitize nested objects | |
| sanitized[key] = sanitizeWebhookPayload(value) | |
| } else { | |
| // Keep primitives as-is | |
| sanitized[key] = value | |
| } | |
| } | |
| return sanitized | |
| } | |
| /** | |
| * Rate limiting helper for sanitization | |
| * Prevents ReDoS attacks on regex sanitization | |
| */ | |
| export const safeSanitize = ( | |
| input: string, | |
| sanitizer: (s: string) => string, | |
| maxLength = 100000 | |
| ): string => { | |
| if (!input) return '' | |
| // Truncate very long inputs to prevent ReDoS | |
| const truncated = input.length > maxLength | |
| ? input.substring(0, maxLength) + '... [truncated]' | |
| : input | |
| return sanitizer(truncated) | |
| } | |