test: parse the page instead of matching tags with a regex

The inline-script check matched <script\b[^>]*> and then filtered the matched text, so a > inside an attribute value split one tag into a fragment that had already lost the attribute the filter looks for. An html.parser subclass decides on the parsed attributes instead. The i18n test imported unittest twice, once plain and once as a from-import.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-23 02:09:23 +02:00
parent 87c4405aa4
commit 4cc8052a88
2 changed files with 20 additions and 8 deletions

View File

@@ -6,6 +6,7 @@ import subprocess
import sys import sys
import tempfile import tempfile
import unittest import unittest
from html.parser import HTMLParser
from pathlib import Path from pathlib import Path
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
@@ -112,18 +113,29 @@ class TestEscaping(AppRouteMixin, unittest.TestCase):
self.assertIn("&lt;script&gt;alert(&#39;config&#39;)", body) self.assertIn("&lt;script&gt;alert(&#39;config&#39;)", body)
class InlineScriptCollector(HTMLParser):
def __init__(self):
super().__init__()
self.inline = []
def handle_starttag(self, tag, attrs):
if tag != "script":
return
attributes = dict(attrs)
if "src" in attributes or attributes.get("type") == "application/json":
return
self.inline.append(self.get_starttag_text())
class TestContentSecurityPolicy(AppRouteMixin, unittest.TestCase): class TestContentSecurityPolicy(AppRouteMixin, unittest.TestCase):
def test_page_ships_no_executable_inline_script(self): def test_page_ships_no_executable_inline_script(self):
body = self.client.get("/de/").get_data(as_text=True) body = self.client.get("/de/").get_data(as_text=True)
inline = [ collector = InlineScriptCollector()
tag collector.feed(body)
for tag in re.findall(r"<script\b[^>]*>", body)
if "src=" not in tag and 'type="application/json"' not in tag
]
self.assertEqual( self.assertEqual(
inline, collector.inline,
[], [],
"a host CSP can only hash an inline script whose content it knows, " "a host CSP can only hash an inline script whose content it knows, "
"and this one changes with every language", "and this one changes with every language",

View File

@@ -2,8 +2,8 @@ import re
import shutil import shutil
import tempfile import tempfile
import unittest import unittest
import unittest.mock
from pathlib import Path from pathlib import Path
from unittest import mock
import yaml import yaml
@@ -170,7 +170,7 @@ class TestCatalogMerge(unittest.TestCase):
) )
def test_an_unsupported_code_never_becomes_a_path(self): def test_an_unsupported_code_never_becomes_a_path(self):
with mock.patch.object(i18n, "read_catalog") as read: with unittest.mock.patch.object(i18n, "read_catalog") as read:
self.assertEqual(i18n.catalog("../content/de"), {}) self.assertEqual(i18n.catalog("../content/de"), {})
read.assert_not_called() read.assert_not_called()