fcf433a736a8670c9da0e2af3ac54db24b0aaa3b
braney
  Mon Aug 24 14:47:47 2026 -0700
htmlSanitize: rename the ids that come in with the HTML, refs #38126

The description HTML is printed inside a page of ours, and it is our own
JavaScript that looks ids up.  A page that carries an id we already use puts
two elements of that name in one document, and getElementById returns whichever
comes first.  Two ids in the public hub pages collide with ours today, one of
them "content".  An id also becomes a property of that name on window, which
reaches the guards we write as "typeof X !== 'undefined' && X".

Every id, and every name on an anchor, now gets the prefix descPage- .  The
hyphen means the window property it makes can never be spelled as a JavaScript
name, so it cannot stand in for one of our globals either.  A link to a name on
the same page, href="#x", is rewritten with the same prefix and keeps working.
A link that names another page is left alone: it leaves our page for the hub's
own file, where the names are unchanged.

Measured over the 5390 description pages of the public hubs: 1643 ids and
anchor names renamed, no id left without the prefix, and the number of same
page links with nothing to point at is 22 before and 22 after, the same ones.
No page loses reader-visible text and the hubCheck warnings are unchanged at
118 pages, since a reader sees nothing of this.

diff --git src/inc/htmlSanitize.h src/inc/htmlSanitize.h
index 0fa9d829682..da4f8feea45 100644
--- src/inc/htmlSanitize.h
+++ src/inc/htmlSanitize.h
@@ -1,25 +1,31 @@
 /* htmlSanitize - reduce a piece of HTML that came from outside to an allowlist of
  * elements, attributes and style properties. */
 
 /* Copyright (C) 2026 The Regents of the University of California
  * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */
 
 #ifndef HTMLSANITIZE_H
 #define HTMLSANITIZE_H
 
 #ifndef COMMON_H
 #include "common.h"
 #endif
 
+#define htmlSanitizeIdPrefix "descPage-"
+/* Put in front of every id, and every name on an anchor, that comes in with the HTML.
+ * The HTML is printed inside a page of ours, so without this a name it chose could be
+ * one our own JavaScript looks up, or one of the globals our pages test for.  A link to
+ * a name on the same page is rewritten with the same prefix and keeps working. */
+
 char *htmlSanitize(char *html);
 /* Return a cloned copy of html holding only allowlisted elements, attributes and style
  * properties.  An element that is not on the keep list loses its tag but keeps its text,
  * so a whole pasted document comes out as the article it was meant to be.  A few elements
  * that carry no text for a reader, script and style and form among them, go away with
  * their contents.  Returns NULL if html is NULL.  Never aborts, whatever the input. */
 
 char *htmlSanitizeReport(char *html, struct slName **retRemoved);
 /* Like htmlSanitize, and if retRemoved is not NULL also return a list of one-line messages
  * naming each kind of thing that was removed.  The list is NULL when nothing was removed. */
 
 #endif /* HTMLSANITIZE_H */