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/hgUserSuggestion/hgUserSuggestion.c src/hg/hgUserSuggestion/hgUserSuggestion.c
index 8010f1dc437..850681c1a05 100644
--- src/hg/hgUserSuggestion/hgUserSuggestion.c
+++ src/hg/hgUserSuggestion/hgUserSuggestion.c
@@ -386,35 +386,37 @@
     "<B>Your suggestion details:</B><BR>"
     "<pre>%s</pre>"
     "</p>",
     summary, details);
 if (captchaScore > -1.0)
     hPrintf("<p>(google captcha score: %g)</p>\n", captchaScore);
 }
 
 void printInvalidForm(double captchaScore, boolean robot)
 /* display invalid form page */
 {
 if (captchaScore > -1.0)
     {
     if (robot)
 	{
-        char *sName=cartUsualString(cart,"suggestName","no name entered");
-        char *sEmail=cartUsualString(cart,"suggestEmail","no email entered");
-        char *sCategory=cartUsualString(cart,"suggestCategory","no category entered");
-        char *sSummary=cartUsualString(cart,"suggestSummary","no summary entered");
-        char *sDetails=cartUsualString(cart,"suggestDetails","no details entered");
+        // these come from the cart (user input) and are echoed into a mailto: URL
+        // inside an href attribute, so cgi-encode them (URL- and attribute-safe) (XSS)
+        char *sName=cgiEncode(cartUsualString(cart,"suggestName","no name entered"));
+        char *sEmail=cgiEncode(cartUsualString(cart,"suggestEmail","no email entered"));
+        char *sCategory=cgiEncode(cartUsualString(cart,"suggestCategory","no category entered"));
+        char *sSummary=cgiEncode(cartUsualString(cart,"suggestSummary","no summary entered"));
+        char *sDetails=cgiEncode(cartUsualString(cart,"suggestDetails","no details entered"));
 	hPrintf(
         "<h2>Invalid Form.</h2>"
 	"<p>"
 	"Congratulations, your google captcha score (%g) appears to qualify "
         "you as a robot.  If this is in error, please email our support email:"
         "&nbsp;<a href='mailto:%s?subject=suggestion "
         "failed captcha&body=Failed captcha test in suggestion form, "
         "score: %g, %s, %s, %s, %s, %s'>I am *not* a ROBOT !</a>"
 	"</p>", captchaScore, mailToAddr(), captchaScore, sName, sEmail, sCategory, sSummary, sDetails
 	);
 	}
     else
 	{
 	hPrintf(
         "<h2>Invalid Form.</h2>"