71366eb92d89bbb2cf87e2a9293ea019b63981a4 braney Fri Aug 21 10:22:02 2026 -0700 htmlSanitize: keep odd characters out of the messages we hand back, refs #38126 An attribute name in HTML can hold almost anything, and the name goes into a message that hubCheck prints to a terminal. Name the attribute only when it reads like a name. diff --git src/lib/htmlSanitize.c src/lib/htmlSanitize.c index 07b85af685a..cf5f1187685 100644 --- src/lib/htmlSanitize.c +++ src/lib/htmlSanitize.c @@ -223,30 +223,42 @@ } else if (*s == '=') expectValue = TRUE; else if (*s == '>') return s; } return NULL; } static boolean isNameChar(char c) /* Is c part of an element or attribute name? */ { return isalnum((unsigned char)c) || c == ':' || c == '_' || c == '-' || c == '.'; } +static boolean allNameChars(char *s) +/* Is every character in s one that belongs in a name? A message we hand back names an + * attribute the page wrote, and that text can end up in a terminal. */ +{ +for (; *s != 0; ++s) + { + if (!isNameChar(*s)) + return FALSE; + } +return TRUE; +} + static char *tagName(char *s, char *name, int nameSize) /* Copy the element name starting at s into name, lower cased. Return the first character * after the name. */ { int i = 0; while (isNameChar(*s)) { if (i < nameSize-1) name[i++] = *s; ++s; } name[i] = 0; tolowers(name); return s; } @@ -572,31 +584,31 @@ while ((s = nextAttribute(s, tagEnd, &name, &nameLen, &val, &valLen)) != NULL) { if (nameLen == 0 || nameLen > 128) continue; char attr[129]; memcpy(attr, name, nameLen); attr[nameLen] = 0; tolowers(attr); char key[256]; safef(key, sizeof key, "%s.%s", element, attr); if (hashLookup(attrHash, key) == NULL) { safef(key, sizeof key, "*.%s", attr); if (hashLookup(attrHash, key) == NULL) { - if (startsWith("on", attr)) + if (startsWith("on", attr) && allNameChars(attr)) noteRemoved(san, "removed the attribute %s", attr); continue; } } char *value = cloneStringZ(val == NULL ? "" : val, valLen); if (sameString(attr, "style")) { char *style = filterStyle(value, san); if (style != NULL) { dyStringAppend(san->out, " style=\""); appendEscaped(san->out, style); dyStringAppendC(san->out, '"'); freeMem(style); }