fix: safe attribute construction for data-ol-link-track in 4 templates - #13187
Merged
Merged
Conversation
modal_links.html, title_and_author.html, onboarding_card.html, and header_dropdown.html each built the tracking attribute via %-string formatting spliced into the tag unquoted. Templetor's bare $var escapes <, >, &, and " but not whitespace, so a tracking value containing a space injects a real new HTML attribute (e.g. onmouseover=...) since the escaped quote characters become inert " text, not real delimiters. Confirmed exploitable against the prior code with a real render + injection payload before applying this fix. Mirrors the fix already applied to Follow.html in #12985: place the value inside a static, template-source quote character via $if var: attr="$var" instead of building the whole fragment in Python.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #13186. Follow-up to #12985's review, which found the same unsafe pattern in
modal_links.htmland flagged it out of scope. A full sweep during that review turned up 3 more instances of the identical bug.Problem
openlibrary/templates/type/edition/modal_links.html,title_and_author.html,home/onboarding_card.html, andlib/header_dropdown.htmleach built their tracking attribute (data-ol-link-track) via Python%-string formatting, then spliced the wholeattr="value"fragment into the tag as a single unquoted token.The real, confirmed mechanism (not tag/script breakout β Open Library's
render_templatepipeline already HTML-escapes<,>,&,"for a bare$var): a value containing a space injects a real new HTML attribute, because the escaped"characters become inert"text rather than actual quote delimiters once escaped, effectively making the "quoted" attribute unquoted. E.g.ga_data = "x onmouseover=alert(document.cookie)//"renders as:Confirmed via a real test render against the prior code (see the added test file β verified red against old code, green against the fix, not just reasoned about). None of today's real callers pass anything but hardcoded string literals, so this isn't attacker-reachable through any live code path right now β same defense-in-depth situation Follow.html was in before #12985.
Fix
Same pattern as #12985: place the value inside a static, template-source literal quote character via
$if var: attr="$var", instead of building the wholeattr="value"fragment in Python and splicing it in unquoted. This can't be broken out of regardless of what characters (including whitespace) the value contains.Testing
openlibrary/tests/test_link_track_attribute_escaping.pyβ new tests for all 4 fixes, each proving the injection is blocked with a real payload (x onmouseover=alert(document.cookie)//) rendered through the actual template engine and parsed with BeautifulSoup. Verified red against the pre-fix code, green after.modal_links.html/title_and_author.htmlduplicate an internalicon_link()helper not reachable with dynamic data through any real top-level call site today, so those two are covered via a small dedicated test fixture (openlibrary/templates/tests/icon_link_pattern_check.html) that mirrors the exact fixed pattern.openlibrary/tests/test_templates.pysuite (769 tests) green. Broader regression sweep (openlibrary/tests/,openlibrary/plugins/upstream/tests/,openlibrary/plugins/openlibrary/tests/, 1920+ tests) green aside from 3 pre-existing, unrelated failures (missingsitecontext, reproducible in isolation on a clean checkout, nothing to do with any file this PR touches).data-ol-link-trackattributes present with the expected values.openlibrary/scripts/a11y/pa11y_runner.pyreferenced in internal docs doesn't exist in this codebase currently, so it couldn't be run. Risk is low regardless β this change only alters how an existing non-semantic analytics attribute is constructed internally; no DOM structure, semantics, or interactive elements changed.