@orchard9ai/error-handling
Version:
Federated error handling package with go-core-http-toolkit format support and logging integration
69 lines (59 loc) • 1.79 kB
text/typescript
/**
* Sanitization utilities for error messages to prevent XSS
*/
/**
* HTML entities that need escaping
*/
const htmlEntities: Record<string, string> = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/',
};
/**
* Escape HTML in string to prevent XSS
*/
export function escapeHtml(text: string): string {
return String(text).replace(/[&<>"'\/]/g, (char) => htmlEntities[char] || char);
}
/**
* Sanitize error message for safe display
*/
export function sanitizeErrorMessage(message: unknown): string {
if (typeof message !== 'string') {
return escapeHtml(String(message));
}
// Remove any potential script tags or event handlers
const cleaned = message
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
.replace(/on\w+\s*=\s*["'][^"']*["']/gi, '')
.replace(/javascript:/gi, '');
return escapeHtml(cleaned);
}
/**
* Sanitize object for safe display (removes sensitive fields)
*/
export function sanitizeErrorDetails(details: Record<string, any>): Record<string, string> {
const sanitized: Record<string, string> = {};
const sensitiveKeys = ['password', 'token', 'secret', 'api_key', 'apiKey', 'authorization'];
for (const [key, value] of Object.entries(details)) {
// Skip sensitive fields
if (sensitiveKeys.some(sensitive => key.toLowerCase().includes(sensitive))) {
continue;
}
// Sanitize the value
sanitized[key] = sanitizeErrorMessage(value);
}
return sanitized;
}
/**
* Remove stack traces and sensitive info from error objects
*/
export function sanitizeError(error: Error): { message: string; name: string } {
return {
message: sanitizeErrorMessage(error.message),
name: sanitizeErrorMessage(error.name)
};
}