304e190d0af4be54569ac20edc26999673c44f8b braney Tue Aug 18 11:05:19 2026 -0700 hgTrackUi, hui: encode trackDb-derived label text consistently, refs #38123 diff --git src/hg/hgTrackUi/hgTrackUi.c src/hg/hgTrackUi/hgTrackUi.c index 4a883081e32..e664821afe3 100644 --- src/hg/hgTrackUi/hgTrackUi.c +++ src/hg/hgTrackUi/hgTrackUi.c @@ -3917,32 +3917,34 @@ "(<A HREF=\"%s?%s=%s&db=%s&c=%s&hgTracksConfigPage=configure" "&hgtgroup_%s_close=0#%sGroup\" title='%s tracks in track configuration " "page'><IMG height=12 src='../images/ab_up.gif'>All %s%s</A>)</B>", hgTracksName(), cartSessionVarName(), cartSessionId(cart),database,chromosome, tdb->grp,tdb->grp,grp->label,grp->label, endsWith(grp->label," Tracks")?"":" tracks"); break; } } grpFreeList(&grps); } // incoming links from Google searches can go directly to a composite child trackUi page: tell users // that they're inside a container now and can go back up the hierarchy if (tdbGetComposite(tdb)) { - printf("<p>This track is a subtrack of the composite container track \"%s\".<br>", tdb->parent->shortLabel); - printf("<a href='hgTrackUi?db=%s&c=%s&g=%s'>Click here</a> to display the \"%s\" container configuration page.", database, chromosome, tdb->parent->track, tdb->parent->shortLabel); + // shortLabel comes from trackDb, which a track hub controls, escape + printf("<p>This track is a subtrack of the composite container track \"%s\".<br>", + htmlEncode(tdb->parent->shortLabel)); + printf("<a href='hgTrackUi?db=%s&c=%s&g=%s'>Click here</a> to display the \"%s\" container configuration page.", database, chromosome, tdb->parent->track, htmlEncode(tdb->parent->shortLabel)); } } puts("<BR><BR>"); if (tdbIsSuperTrackChild(tdb)) showSupertrackInfo(tdb); if (ct && sameString(tdb->type, "maf")) tdb->canPack = TRUE; else if (sameString(tdb->track, WIKI_TRACK_TABLE)) // special case wikiTrack (there's no trackDb entry); fixes redmine 2395 tdb->canPack = TRUE; else if (sameString(tdb->type, "halSnake")) @@ -4604,47 +4606,49 @@ tdb = dupTdbFrom(tdb, dup); } if(cartOptionalString(cart, "ajax")) { // html is going to be used w/n a dialog in hgTracks.js so serve up stripped down html // still need CSP2 header for security printf("%s", getCspMetaHeader()); trackUi(tdb, tdbList, ct, TRUE); cartRemove(cart,"ajax"); jsInlineFinish(); } else { - char title[1000]; + // htmlNoEscape() below lets the <span> through, so the labels themselves have to be + // escaped here - they come from trackDb, which a track hub controls + struct dyString *title = dyStringNew(0); if (tdb->parent) { - safef(title, sizeof title, + dyStringPrintf(title, // TODO: replace in-line styling with class "<span style='background-color: #c3d4f4; " "padding-left: 10px; padding-right: 10px;" "margin-right: 10px; margin-left: -8px;'>" "%s</span> %s", - tdb->parent->shortLabel, tdb->shortLabel); + htmlEncode(tdb->parent->shortLabel), htmlEncode(tdb->shortLabel)); } else - safef(title, sizeof title, "%s", tdb->shortLabel); + dyStringPrintf(title, "%s", htmlEncode(tdb->shortLabel)); char *titleEnd = (tdbIsSuper(tdb) ? "Tracks" : tdbIsDownloadsOnly(tdb) ? DOWNLOADS_ONLY_TITLE : "Track Settings"); htmlNoEscape(); // allow HTML tags to format title blue bar (using short label) - cartWebStart(cart, database, "%s %s", title, titleEnd); + cartWebStart(cart, database, "%s %s", title->string, titleEnd); htmlDoEscape(); trackUi(tdb, tdbList, ct, FALSE); printf("<BR>\n"); jsonPrintGlobals(); webEnd(); } } char *excludeVars[] = { "submit", "Submit", "g", "fileUrl", "track", "sourceDb", NULL, "ajax", NULL,}; int main(int argc, char *argv[]) /* Process command line. */ { long enteredMainTime = clock1000(); /* 0, 0, == use default 10 second for warning, 20 second for immediate exit */