"""End-to-end regression tests for the stored-XSS fix (GHSA-v5mq-3xhg-98m9).
These exercise the two production sinks:
* ``elements_to_html`` — the assembled HTML document,
* ``ElementMetadata.text_as_html`` — which some callers return to clients verbatim,
feeding them the exact proof-of-concept from the advisory and asserting every
vector is neutralized, while legitimate formatting is preserved.
"""
from __future__ import annotations
import re
from urllib.parse import urlparse
from bs4 import BeautifulSoup
from unstructured.documents.elements import ElementMetadata, Text
from unstructured.partition.html import partition_html
from unstructured.partition.html.convert import elements_to_html
# -- The advisory's proof-of-concept document. --
MALICIOUS_HTML = (
'
'
'
hello'
'
'
'click me'
""
)
def _partition_v2(html_text: str):
return list(partition_html(text=html_text, html_parser_version="v2"))
def _all_text_as_html(elements) -> str:
return " ".join(e.metadata.text_as_html or "" for e in elements)
def _href_values(html: str) -> list[str]:
return [
str(anchor["href"])
for anchor in BeautifulSoup(html, "html.parser").find_all("a", href=True)
]
class DescribeElementsToHtmlIsInert:
"""The four advisory vectors must not survive into elements_to_html output."""
def it_strips_event_handler_attributes(self):
out = elements_to_html(_partition_v2(MALICIOUS_HTML), no_group_by_page=True)
assert "onmouseover" not in out
assert "onerror" not in out
assert "onload" not in out
def it_neutralizes_javascript_hrefs(self):
out = elements_to_html(_partition_v2(MALICIOUS_HTML), no_group_by_page=True)
assert "javascript:" not in out.lower()
def it_has_no_live_svg_from_attribute_breakout(self):
# -- title='">'
'