983b7eff4b1c516c9cb7bb56cc1399216a127d51 max Wed Aug 19 04:02:39 2026 -0700 address v503 preview1 code review (#38141): escaping and oauth fixes Fixes the six items Brian raised reviewing the XSS sweep (#38057) and the BLAT-results group work (#38086): - hgGenome/configure.c, hgPal.c: drop htmlEncode() on cartWebStart title args; cartWebStart already escapes the title, so this was double-escaping. - hgSession.c doReSaveSession: htmlEncode the user name and pass the encoded name to getSessionLink (same fix already applied at line 1544). - hgUserSuggestion.c printInvalidForm: cgiEncode the five cart values echoed into the mailto: href (reachable on the robot/captcha path). - hgSearch.c: cgiEncode db for the hgTracks URL query parameter instead of reusing the JSON-escaped copy meant for the JS string literal. - hgLogin.c oauthReturn: clone oauth_provider before cartRemove frees it, so the later oauthFetchIdentity call is not a read-after-free. - customFactory.c checkGroup: only accept group=blat when blatResultsGroup is on, matching hgTracks; otherwise the group is never created and the track would orphan into 'other'. refs #38141, refs #38057, refs #38086 diff --git src/hg/hgSearch/hgSearch.c src/hg/hgSearch/hgSearch.c index 726cce77400..5c28caec17e 100644 --- src/hg/hgSearch/hgSearch.c +++ src/hg/hgSearch/hgSearch.c @@ -606,31 +606,33 @@ trackHubFixName(trackName); puts("Content-type:text/html\n"); puts("\n\n"); printf("\n"); printf(" can break out (XSS). char *jsDb = jsonStringEscape(db); char *jsSearch = jsonStringEscape(userSearch); printf("addRecentSearch(\"%s\", \"%s\", {\"label\": \"%s\", \"value\": \"%s\", \"id\": \"%s\"});\n", jsDb, jsSearch, jsSearch, jsSearch, newPosBuf); printf("window.location.href=\"../cgi-bin/hgTracks?"); - printf("db=%s", jsDb); + // db here is a URL query parameter, so cgi-encode it rather than reuse the JS-escaped jsDb + char *urlDb = cgiEncode(db); + printf("db=%s", urlDb); printf("&position=%s", newPosBuf); if (!sameString(trackName, "chromInfo")) printf("&%s=pack", trackName); printf("&hgFind.matches=%s", hgp->singlePos->name); if (track && track->parent) { if (tdbIsSuperTrackChild(track)) printf("&%s=show", track->parent->track); else { // tdb is a subtrack of a composite or a view printf("&%s_sel=1&%s_sel=1", trackName, track->parent->track); } } printf("\"\n");