All files / utils html-sanitize.ts

76.92% Statements 20/26
62.5% Branches 5/8
100% Functions 1/1
76.92% Lines 20/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60                                          148x 148x 148x 148x 148x   148x 143x 143x 126x 126x     17x   17x 17x           17x 17x         17x 17x       17x 17x   148x    
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
// SPDX-License-Identifier: Apache-2.0
 
/**
 * @module Utils/HtmlSanitize
 * @description Shared HTML sanitization helpers used across the generation,
 * validation, and quality-scoring pipelines.
 */
 
/**
 * Remove all `<script>…</script>` blocks from an HTML string, replacing each
 * with a single space.
 *
 * Uses iterative index-based scanning instead of a single-pass regex so that
 * CodeQL does not flag the pattern as an insecure HTML tag filter
 * (`js/bad-tag-filter`).
 *
 * @param html - HTML string to strip
 * @returns The HTML with script blocks replaced by spaces
 */
export function stripScriptBlocks(html: string): string {
  const OPEN = '<script';
  const CLOSE = '</script';
  let result = '';
  let pos = 0;
  const lower = html.toLowerCase();
 
  while (pos < html.length) {
    const openIdx = lower.indexOf(OPEN, pos);
    if (openIdx < 0) {
      result += html.slice(pos);
      break;
    }
    // Copy everything before the opening <script
    result += html.slice(pos, openIdx);
    // Find the end of the opening tag
    const openEnd = html.indexOf('>', openIdx);
    Iif (openEnd < 0) {
      // Malformed — no closing `>`, keep rest as-is
      result += html.slice(openIdx);
      break;
    }
    // Find the closing </script...> tag
    const closeIdx = lower.indexOf(CLOSE, openEnd + 1);
    Iif (closeIdx < 0) {
      // No closing tag — drop the rest
      result += ' ';
      break;
    }
    const closeEnd = html.indexOf('>', closeIdx);
    Iif (closeEnd < 0) {
      result += ' ';
      break;
    }
    result += ' ';
    pos = closeEnd + 1;
  }
  return result;
}