mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: harden auth, security headers, SVG sanitization, and pipeline ownership
- Add password strength validation (8+ chars, uppercase, lowercase, number) - Add username validation rules - Optimize API key lookup with SHA-256 prefix (O(1) vs O(n) scan) - Require password change on default admin first login - Revoke API keys on password change - Add session cleanup cron (hourly expired session purge) - Add Permissions-Policy, HSTS, and CSP security headers in production - Strengthen SVG sanitizer: block XInclude, foreignObject, processing instructions, javascript/data/file URI schemes - Add userId ownership to pipelines with authorization checks - Add keyPrefix column to api_keys table - Update integration tests for new auth behavior
This commit is contained in:
@@ -20,15 +20,29 @@ function sanitizeSvg(buffer: Buffer): Buffer {
|
||||
throw new Error(`SVG exceeds maximum size of ${MAX_SVG_SIZE / 1024 / 1024}MB`);
|
||||
}
|
||||
let svg = buffer.toString("utf-8");
|
||||
// Remove DOCTYPE to prevent XXE
|
||||
svg = svg.replace(/<!DOCTYPE[^>]*>/gi, "");
|
||||
// Remove DOCTYPE (XXE prevention, including internal subsets)
|
||||
svg = svg.replace(/<!DOCTYPE[^>[]*(?:\[[^\]]*\])?>/gi, "");
|
||||
// Remove XML processing instructions except <?xml version...?>
|
||||
svg = svg.replace(/<\?(?!xml\s)[^?]*\?>/gi, "");
|
||||
// Remove XInclude elements and namespace declarations
|
||||
svg = svg.replace(/<[^>]*xi:include[^>]*\/?>/gi, "");
|
||||
svg = svg.replace(/xmlns:xi\s*=\s*["'][^"']*["']/gi, "");
|
||||
// Remove script tags
|
||||
svg = svg.replace(/<script[\s\S]*?<\/script>/gi, "");
|
||||
// Remove event handlers (onload, onclick, etc.)
|
||||
// Remove foreignObject elements (can embed arbitrary HTML)
|
||||
svg = svg.replace(/<foreignObject[\s\S]*?<\/foreignObject>/gi, "");
|
||||
svg = svg.replace(/<foreignObject[^>]*\/>/gi, "");
|
||||
// Remove event handlers (onload, onclick, onerror, etc.)
|
||||
svg = svg.replace(/\bon\w+\s*=/gi, "data-removed=");
|
||||
// Remove external resource references
|
||||
// Block dangerous URI schemes in href attributes
|
||||
svg = svg.replace(/xlink:href\s*=\s*["']https?:\/\//gi, 'xlink:href="data:,');
|
||||
svg = svg.replace(/href\s*=\s*["']https?:\/\//gi, 'href="data:,');
|
||||
svg = svg.replace(/href\s*=\s*["']javascript:/gi, 'href="data:,');
|
||||
svg = svg.replace(/href\s*=\s*["']data:text\/html/gi, 'href="data:,');
|
||||
svg = svg.replace(/href\s*=\s*["']file:/gi, 'href="data:,');
|
||||
// Block use elements referencing external resources
|
||||
svg = svg.replace(/url\s*\(\s*["']?https?:\/\//gi, 'url("data:,');
|
||||
svg = svg.replace(/url\s*\(\s*["']?file:/gi, 'url("data:,');
|
||||
return Buffer.from(svg, "utf-8");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user