Input Sanitization
132 LOC · The security backbone shared by both the Service Worker and the Loader. Uses the battle-tested xss library (js-xss) as the primary filter, with additional defense-in-depth layers for URI schemes, event handlers, and JSON injection.
Architecture
Works in both contexts without DOM dependency:
Service Worker
sanitizeUrlParams() on every fetch intercepted URL.safeJsonForScript() before HTML injection.
Loader (Main Thread)
sanitizeValue() on fallback parameter capture. Also used on referrer in message handler.
sanitizeValue() — 5-Layer Pipeline
Each value passes through 5 sequential security layers:
| Layer | Protection | Implementation |
|---|---|---|
| 1. XSS Library | HTML tag stripping | xssFilter(value, options) — strips ALL HTML tags, removes script/style/iframe/object/embed/form body content |
| 2. Control Chars | Null bytes & invisible characters | Regex removes \0 and control chars \x01-\x08, \x0B, \x0C, \x0E-\x1F, \x7F |
| 3. URI Schemes | JavaScript/Data/VBScript execution | Replaces javascript:, data:, vbscript: with blocked: |
| 4. Event Handlers | DOM event injection | Replaces onXxx= patterns with blocked= |
| 5. Truncation | DoS / buffer overflow | Max 500 characters per value (MAX_PARAM_LENGTH) |
XSS Library Configuration
const XSS_OPTIONS = {
whiteList: {}, // No tags allowed at all
stripIgnoreTag: true, // Strip tags not in whitelist
stripIgnoreTagBody: [ // Remove entire content of dangerous tags:
'script', 'style', 'noscript',
'iframe', 'object', 'embed', 'form'
],
stripBlankChar: true, // Remove zero-width chars
onIgnoreTagAttr: () => '', // Remove all attributes
escapeHtml: (html) => html // Don't double-encode (we want text, not entities)
};sanitizeUrlParams() — Parameter Protection
Additional security measures applied at the parameter level:
| Protection | Limit | Purpose |
|---|---|---|
| Param count limit | 50 params max | Anti-DoS: prevents processing thousands of params |
| Key sanitization | [a-zA-Z0-9_\-\.~] only, 100 char max | Restricts keys to safe character set |
| Prototype pollution | Block __proto__, constructor, prototype | Prevents object prototype manipulation |
| Value sanitization | Full sanitizeValue() pipeline | 5-layer XSS protection on every value |
safeJsonForScript() — Injection Prevention
Applied after JSON.stringify() and before inline<script> injection. Prevents context-escape attacks:
| Character | Escaped To | Attack Prevented |
|---|---|---|
< | \u003c | </script> breakout |
> | \u003e | Tag injection |
$ | \u0024 | Template literal injection |
U+2028 | \u2028 | JS line separator (syntax break) |
U+2029 | \u2029 | JS paragraph separator |
& | \u0026 | HTML entity injection |
' | \u0027 | Single-quote breakout |
= | \u003d | Attribute injection |
Constants
| Constant | Value | Purpose |
|---|---|---|
MAX_PARAM_LENGTH | 500 | Max characters per parameter value |
MAX_PARAMS_COUNT | 50 | Max number of URL parameters processed |
Exports
// Named exports used by service-worker.js and loader.js:
export { sanitizeValue } // Single value sanitization
export { sanitizeUrlParams } // Full URL params sanitization
export { safeJsonForScript } // JSON injection escaping
export { MAX_PARAM_LENGTH } // For external validation
export { MAX_PARAMS_COUNT } // For external validation