, nicht * aber " und '. Da escapte Werte per innerHTML in ein title="..."-Attribut * eingesetzt werden, konnte ein Header-/Zellwert wie * `Spalte" onmouseover="alert(1)` aus dem Attribut ausbrechen. */ class BankUploadPreviewXssTest extends TestCase { protected string $testName = 'Test 66: Kein DOM-XSS in der Bankimport-Vorschau (esc() escaped Anführungszeichen)'; public function run(): void { $viewFile = __DIR__ . '/../src/Views/bank/upload.php'; $content = file_get_contents($viewFile); $this->assert( $content !== false, 'View-Datei bank/upload.php ist lesbar' ); $this->assert( str_contains($content, "replace(/\"/g,'"')") && str_contains($content, "replace(/'/g,''')"), 'esc() escaped sowohl " als auch \' zusätzlich zu &, < und >' ); $node = trim((string)shell_exec('command -v node')); if ($node === '') { $this->assert(true, 'node nicht verfügbar – Escaping nur per Quelltext-Check geprüft'); return; } if (!preg_match('/function esc\(str\) \{.*?\n \}/s', $content, $m)) { $this->assert(false, 'esc()-Funktion konnte aus der View-Datei extrahiert werden'); return; } $script = $m[0] . "\nconsole.log(esc('Spalte\" onmouseover=\"alert(1)'));"; $tmp = $this->tempPath('.js'); file_put_contents($tmp, $script); $output = shell_exec(escapeshellarg($node) . ' ' . escapeshellarg($tmp) . ' 2>&1'); $this->assert( $output !== null && !str_contains($output, '" onmouseover="'), 'esc() liefert für einen bösartigen Zellwert kein aus dem title-Attribut ausbrechendes Ergebnis' ); $this->assert( $output !== null && str_contains($output, '"'), 'esc() liefert für einen bösartigen Zellwert das erwartete "-Escaping' ); } }