53 lines
1.4 KiB
Python
53 lines
1.4 KiB
Python
import json
|
|
import subprocess
|
|
from html.parser import HTMLParser
|
|
from pathlib import Path
|
|
from urllib.parse import urljoin
|
|
|
|
|
|
FRONTEND = Path(__file__).parent.parent / "frontend"
|
|
RENDERER = FRONTEND / "markdown.js"
|
|
|
|
|
|
class ScriptSourceParser(HTMLParser):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.sources = []
|
|
|
|
def handle_starttag(self, tag, attrs):
|
|
if tag == "script":
|
|
source = dict(attrs).get("src")
|
|
if source:
|
|
self.sources.append(source)
|
|
|
|
|
|
def test_markdown_renderer_escapes_raw_html_before_rendering_heading():
|
|
payload = "# <img src=x onerror=alert(document.domain)>"
|
|
script = (
|
|
f"const render = require({json.dumps(str(RENDERER))});"
|
|
f"process.stdout.write(render({json.dumps(payload)}));"
|
|
)
|
|
|
|
result = subprocess.run(
|
|
["node", "-e", script],
|
|
check=True,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
|
|
assert result.stdout == (
|
|
"<h1><img src=x onerror=alert(document.domain)></h1>"
|
|
)
|
|
|
|
|
|
def test_markdown_script_resolves_inside_dashboard_subpath():
|
|
parser = ScriptSourceParser()
|
|
parser.feed((FRONTEND / "index.html").read_text())
|
|
markdown_source = next(
|
|
source for source in parser.sources if source.endswith("markdown.js")
|
|
)
|
|
|
|
assert urljoin(
|
|
"https://forge.alexanderwhitestone.com/dashboard/", markdown_source
|
|
) == "https://forge.alexanderwhitestone.com/dashboard/static/markdown.js"
|