In-app reader
justhtml through 1.9.1 allows denial of service via deeply nested HTML. During parsing, JustHTML.__init__() always reaches TreeBuilder.finish(), which unconditionally calls _populate_selectedcontent(). That function recursively traverses the DOM via _find_elements() / _find_element() without a depth bound, allowing attacker-controlled deeply nested input to trigger an unhandled RecursionError on CPython. Depending on the host application's exception handling, this can abort parsing, fail requests, or terminate a worker/process.
TreeBuilder.finish() (treebuilder.py#L476) unconditionally calls _populate_selectedcontent(self.document) at line 494. _populate_selectedcontent() (treebuilder.py#L1243) calls _find_elements() (treebuilder.py#L1280) to recursively search the DOM tree for elements:
def _find_elements(self, node: Any, name: str, result: list[Any]) -> None:
"""Recursively find all elements with given name."""
if node.name == name:
result.append(node)
if node.has_child_nodes():
for child in node.children:
self._find_elements(child, name, result) # recursive call
Discussion
Sign in to join the discussion.
Keep reading
Optional: create a free account to save items, track programs, and sync across web + app. Reading stays free.