PRIX / src /utils /sanitizer.ts
Rachit-Tw's picture
Upload 169 files
9284ad7 verified
Raw
History Blame Contribute Delete
3.54 kB
/**
* 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)
}