4037b582757f86eed1c5559eca9ccc7af85c1496
braney
  Fri Aug 21 10:00:49 2026 -0700
lib: add htmlSanitize, an allowlist filter for HTML written elsewhere, refs #38126

htmlSanitize() takes a piece of HTML and returns a copy holding only the
elements, attributes and style properties on its lists.  An element on the
keep list survives with its allowed attributes.  A short list of elements
that carry nothing for a reader, script and style and form among them, is
dropped along with its contents.  Every other element loses its tag and
keeps its text, so a whole document that somebody saved and pasted in comes
out as the article it was meant to be.

The lists come from a survey of all 5390 description pages reachable from
the public hub list, so they are sized to what hubs actually write.  The
style attribute is filtered a property at a time, and href and src are
checked for a scheme we do not print, after decoding entities and padding.
An iframe is kept only when it plays a video from one of a few hosts, and
then with a sandbox attribute.

htmlSanitizeReport() returns the same copy plus a list of one-line messages
naming what came out, for hubCheck to show a hub author.

The tokenizer is hand written and forgiving.  It never aborts and always
returns something, because the HTML it will be handed is often broken.
lib/htmlPage.c cannot be reused for this: its parser aborts on bad input.

diff --git src/inc/htmlSanitize.h src/inc/htmlSanitize.h
new file mode 100644
index 00000000000..0fa9d829682
--- /dev/null
+++ src/inc/htmlSanitize.h
@@ -0,0 +1,25 @@
+/* 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
+
+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 */