a4befd9382fadf413884d2215012535d5d667063
braney
  Mon Aug 17 13:46:45 2026 -0700
hgApi, hgTracks: tighten callback parameter validation, refs #38126 #38057

Add isValidJsonpCallback() and apply it to the callback-name paths in
apiOut() and the hgTracks jsonp output, so only C-symbol dotted names are
echoed back.

diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index 6f695dd6b82..c9ef24b90c0 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -6119,38 +6119,43 @@
     jsonObjectAdd(jsonForClient, "newWinWidth", newJsonNumber(newWinWidth));
     }
 
 /* Save out picture and tell html file about it. */
 if (hvgSide != hvg)
     hvGfxClose(&hvgSide);
 hvGfxClose(&hvg);
 if (measureTiming)
     measureTime("Time completed writing trash hgt png image file");
 
 #ifdef SUPPORT_CONTENT_TYPE
 char *type = cartUsualString(cart, "hgt.contentType", "html");
 if(sameString(type, "jsonp"))
     {
     struct jsonElement *json = newJsonObject(newHash(8));
+    char *jsonp = cartString(cart, "jsonp");
+    // This path only ever emits a wrapped response, so there is no bare form to
+    // fall back to: reject an invalid callback name outright.
+    if (!isValidJsonpCallback(jsonp))
+        errAbort("invalid callback");
 
     printf("Content-Type: application/json\n\n");
     errAbortSetDoContentType(FALSE);
     jsonObjectAdd(json, "track", newJsonString(cartString(cart, "hgt.trackNameFilter")));
     jsonObjectAdd(json, "height", newJsonNumber(pixHeight));
     jsonObjectAdd(json, "width", newJsonNumber(pixWidth));
     jsonObjectAdd(json, "img", newJsonString(pngTn.forHtml));
-    printf("%s(", cartString(cart, "jsonp"));
+    printf("%s(", jsonp);
     hPrintEnable();
     jsonPrint((struct jsonElement *) json, NULL, 0);
     hPrintDisable();
     printf(")\n");
     return;
     }
 else if(sameString(type, "png") || sameString(type, "pdf") || sameString(type, "eps"))
     {
     // following code bypasses html and return png's directly - see redmine 4888
     // NB: Pretty sure the pdf and eps options here are never invoked.  I don't see any
     // calls that would activate eps output, and pdf is locked behind an unused ifdef
     char *file;
     if(sameString(type, "pdf"))
         {
         printf("Content-Disposition: filename=hgTracks.pdf\nContent-Type: application/pdf\n\n");