Skip to content

fix: prevent </script> breakout in HtmlOutput anchor JS literal#1340

Merged
karlkleinpaste merged 1 commit into
crosswire:masterfrom
hyder365:fix/webkit-special-anchor-script-breakout
Jul 1, 2026
Merged

fix: prevent </script> breakout in HtmlOutput anchor JS literal#1340
karlkleinpaste merged 1 commit into
crosswire:masterfrom
hyder365:fix/webkit-special-anchor-script-breakout

Conversation

@hyder365

Copy link
Copy Markdown
Contributor

g_strescape() escapes backslash, double-quote, and C0 control bytes but leaves <, >, and / untouched, so a sword:// fragment of </script><script>PAYLOAD</script> passes through unchanged when interpolated into the inline <script> block in HtmlOutput(). WebKit's HTML parser ends the <script> block at the literal </script> and starts a new <script>PAYLOAD</script> block, which executes arbitrary JavaScript in the file:// origin that wk_html_set_base_uri() hardcodes.

The fragment can originate from any BibleSync UDP multicast peer on the LAN (biblesync_glue.cc:179 constructs the sword:// URL from peer-supplied bible and ref), from argv[1], or from a sword:// href click inside a malicious SWORD module.

Substitute </ with <\/ in the already-escaped anchor (OWASP recommendation) so the HTML parser can no longer see the end of the script block. g_strescape is kept in place to also handle the backslash-and-quote break-out case from #1337.

A self-contained reproducer is in poc/reproducer.c in this branch: it shows that g_strescape("</script><script>alert(1)</script>") returns the input unchanged.

Follow-up to #1337.

@karlkleinpaste

Copy link
Copy Markdown
Contributor

reproducer.c: you named them the same thing, and now i don't know if i should bother keeping the (small) one in this PR.
but i do appreciate the provision of an explicit means to reproduce.

g_strescape() escapes backslash, double-quote, and C0 control bytes but
leaves '<', '>', and '/' untouched, so a sword:// fragment of
"</script><script>PAYLOAD</script>" passes through unchanged when
interpolated into the inline <script> block in HtmlOutput().  WebKit's
HTML parser ends the <script> block at the literal '</script>' and
starts a new <script>PAYLOAD</script> block, which executes arbitrary
JavaScript in the file:// origin that wk_html_set_base_uri() hardcodes.

The fragment can originate from any BibleSync UDP multicast peer on the
LAN (biblesync_glue.cc:179 constructs the sword:// URL from peer-supplied
bible and ref), from argv[1], or from a sword:// href click inside a
malicious SWORD module.

Substitute '</' with '<\/' in the already-escaped anchor (OWASP
recommendation) so the HTML parser can no longer see the end of the
script block.  g_strescape is kept in place to also handle the
backslash-and-quote break-out case from the prior fix (crosswire#1337).
@hyder365 hyder365 force-pushed the fix/webkit-special-anchor-script-breakout branch from 0d7c0c2 to d62cddc Compare July 1, 2026 00:18
@hyder365

hyder365 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

Dropped the reproducer.

@karlkleinpaste karlkleinpaste merged commit d245972 into crosswire:master Jul 1, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants