From d780c602f259874eb0af04e4e3547e3c15f0a083 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 11:25:06 +0000 Subject: [PATCH] Always neutralize javascript: links, independent of fixRelativeURLs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Readability.js always strips javascript: anchors in _postProcessContent via _fixRelativeUris. This port gated the entire fixRelativeUris() step behind the fixRelativeURLs config flag (default false), so with the default configuration javascript: links passed straight through to the output — a regression from upstream. The test corpus masked this because its harness always enables fixRelativeURLs (jsdom always has a base URI). Decouple the two concerns: javascript: neutralization now always runs (it needs no base URL and is a defense-in-depth measure), while absolutizing relative URLs stays opt-in via fixRelativeURLs. Add a regression test exercising the default configuration, and expand the README/UPGRADE security notes to spell out what does and does not survive extraction (event handlers, data: URIs on media, whitelisted video embeds) so callers still run a real sanitizer. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01WPggv1W7LrNiWLDrHas5WU --- README.md | 27 +++++++++++++++++++++++++++ UPGRADE.md | 1 + src/Readability.php | 22 ++++++++++++++++------ test/ReadabilityUnitTest.php | 22 ++++++++++++++++++++++ 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5a4d3f7..e009e8c 100644 --- a/README.md +++ b/README.md @@ -151,8 +151,35 @@ Readability scans and scores HTML elements based on the number of words, links a ## Security +Readability is a content **extractor**, not a sanitizer. The returned +`Article::$content` (and `Article::$contentElement`) is HTML pulled from the +source page — it is *not* safe to render as-is when the input is untrusted. + If you're going to use Readability with untrusted input (whether in HTML or DOM form), we **strongly** recommend you use a sanitizer library like [HTML Purifier](https://github.com/ezyang/htmlpurifier) or [Symfony's HtmlSanitizer](https://symfony.com/doc/current/html_sanitizer.html) to avoid script injection when you use the output of Readability. We would also recommend using [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) to add further defense-in-depth restrictions to what you allow the resulting content to do. The Firefox integration of reader mode uses both of these techniques itself. Sanitizing unsafe content out of the input is explicitly not something we aim to do as part of Readability itself - there are other good sanitizer libraries out there, use them! +Readability removes `