/** * HTML context patterns. * * Detects XSS vectors that are dangerous when a string ends up rendered as HTML. * All patterns use bounded quantifiers to ensure linear-time matching (ReDoS-safe). * * Each entry is { pattern: RegExp, id: string, description: string } * so callers can inspect which rule fired if they need to. */ const HTML_PATTERNS = [ { id: 'html-script-open', description: ']/i, }, { id: 'html-javascript-protocol', description: 'javascript: URI scheme (with optional whitespace/encoding)', // Handles javascript:, j\u0061vascript:, and whitespace variants pattern: /j[\t\n\r ]*a[\t\n\r ]*v[\t\n\r ]*a[\t\n\r ]*s[\t\n\r ]*c[\t\n\r ]*r[\t\n\r ]*i[\t\n\r ]*p[\t\n\r ]*t[\t\n\r ]*:/i, }, { id: 'html-vbscript-protocol', description: 'vbscript: URI scheme', pattern: /vbscript[\t\n\r ]*:/i, }, { id: 'html-data-html', description: 'data:text/html URI — can execute scripts in browsers', pattern: /data[\t\n\r ]*:[\t\n\r ]*text\/html/i, }, { id: 'html-data-xhtml', description: 'data:application/xhtml+xml URI', pattern: /data[\t\n\r ]*:[\t\n\r ]*application\/xhtml/i, }, { id: 'html-data-svg', description: 'data:image/svg+xml URI — can execute scripts', pattern: /data[\t\n\r ]*:[\t\n\r ]*image\/svg\+xml/i, }, { id: 'html-inline-event-handler', description: 'Inline event handler attributes: onclick=, onerror=, onload=, etc.', // \bon ensures we match a word boundary so "phonetic=" is not caught pattern: /\bon\w{1,30}\s*=/i, }, { id: 'html-entity-obfuscated-script', description: 'HTML-entity-encoded