f83fd4fd350727eb3a42a709849bab0c4658ab84
braney
  Fri Aug 21 10:17:16 2026 -0700
htmlSanitize: three fixes from a review of it, refs #38126

Read the scheme of an href or src the way a browser arrives at it.  A browser
turns a numeric character reference into its character before it decides what
the scheme is, and it accepts one written with any number of leading zeros and
with no closing semicolon at all.  Decode those the same way, then insist that
what stands in front of the first slash is either a plain scheme we allow or a
plain path.  A named entity, a backslash or a control character in that part of
the value means we do not print the link, because those are the ways the check
gets walked around.  This keeps the 33 encoded mailto links two hubs write, and
they were the only links in the public hubs the plainer rule would have lost.

Treat a trailing slash on a kept element as the nothing that HTML says it is.
Otherwise <div/> came out as an open div and the rest of our own page sat
inside it.

Remember when the search for a closing tag has run off the end of the input.
Every later search for that same tag runs off the end too, so a page made of
two hundred thousand unclosed tags no longer costs one pass over the page each.

The unit test grows a case for each of the three.

diff --git src/lib/tests/expected/htmlSanitizeTest src/lib/tests/expected/htmlSanitizeTest
index 90d323314cd..6f778d66bfa 100644
--- src/lib/tests/expected/htmlSanitizeTest
+++ src/lib/tests/expected/htmlSanitizeTest
@@ -1,53 +1,72 @@
 in : <html><head><title>T</title><meta charset="utf-8"></head><body class="x"><h2>Head</h2><p>Text</p></body></html>
 out: <h2>Head</h2><p>Text</p>
 
 in : <p>before</p><script>alert(1)</script><style>body{visibility:hidden}</style><p>after</p>
 out: <p>before</p><p>after</p>
      (removed the script element and everything inside it)
      (removed the style element and everything inside it)
 
 in : <p>before</p><script>if (a < b) alert(1)
 out: <p>before</p>
      (removed the script element and everything inside it)
 
 in : <div id="top" class="warn" title="t" onclick="alert(1)">text</div>
 out: <div id="top" title="t">text</div>
      (removed the attribute onclick)
 
 in : <a href="&#106;avascript:alert(1)">one</a> <a href="java&Tab;script:alert(1)">two</a>
 out: <a>one</a> <a>two</a>
      (removed a link that used the javascript: scheme)
+     (removed a link that does not read as a plain web address)
+
+in : <a href="&#0000000106;avascript:alert(1)">three</a> <a href="&#106avascript:alert(1)">four</a>
+out: <a>three</a> <a>four</a>
+     (removed a link that used the javascript: scheme)
+
+in : <a href="jav&#9;ascript:alert(1)">five</a> <a href="java&colon;script:alert(1)">six</a>
+out: <a>five</a> <a>six</a>
+     (removed a link that does not read as a plain web address)
+
+in : <a href="&#109;ailto:help&#64;riken.jp?subject=x">write to us</a>
+out: <a href="&#109;ailto:help&#64;riken.jp?subject=x">write to us</a>
 
 in : <a href="https://genome.ucsc.edu">u</a> <a href="#anchor" target="_blank">a</a>
 out: <a href="https://genome.ucsc.edu">u</a> <a href="#anchor" target="_blank" rel="noopener noreferrer">a</a>
 
 in : <img src="pic.png" alt="a" onerror="alert(1)" width="20">
 out: <img src="pic.png" alt="a" width="20">
      (removed the attribute onerror)
 
 in : <iframe width="560" src="https://www.youtube.com/embed/abc"></iframe><iframe src="https://example.com/x">fallback</iframe>
 out: <iframe width="560" src="https://www.youtube.com/embed/abc" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>
      (removed an iframe, we only allow one that plays a video from a site we know)
 
 in : <p style="color:red;behavior:url(#default#VML);text-align:center;position:fixed">p</p>
 out: <p style="color:red;text-align:center;">p</p>
 
 in : <o:p>word</o:p><vertebrates>more</vertebrates>
 out: wordmore
 
 in : <div><b>bold<p>para
 out: <div><b>bold<p>para</p></b></div>
 
+in : <div style="color:red"/>the rest of the page is not inside that div
+out: <div style="color:red;">the rest of the page is not inside that div</div>
+
+in : <svg><svg><svg><svg>text
+out: text
+     (removed the svg element and everything inside it)
+
 in : <a href=https://example.com/x\">link text</a> and more text
 out: <a href="https://example.com/x\&quot;">link text</a> and more text
 
 in : <form action="/x"><input name="password"><button>Log in</button></form><p>after</p>
 out: <p>after</p>
      (removed the form element and everything inside it)
 
 in : <!DOCTYPE html><!-- <p>hidden</p> --><p>shown</p>
 out: <p>shown</p>
 
 in : <table border="1"><tr><td colspan="2" bgcolor="#eee">cell</td></tr></table>
 out: <table border="1"><tr><td colspan="2" bgcolor="#eee">cell</td></tr></table>