9ad04e0a0b06ec3c4f09ef1b6c3ce6be79b61c68 braney Sun Aug 16 11:56:56 2026 -0700 cart: validate file names read back out of the cart Several cart variables hold the name of a file the server created for a user. Route them through one shared check, isServerUserFilePath(), which accepts the trash directory, the session-data directories and myVariantsDataDir, and apply it both where values enter the cart and where the file names are used. A few of these variables may instead hold a remote URL. Those get their own list and isServerUserFileOrUrl(), because the code that reads them chooses between a fetch and a local open by looking for a protocol. Consolidates two hand-rolled copies of the same test in blatShare.c and customFactory.c, and drops the weaker private copy in sessionData.c. Adds hg/utils/cartFileVarCatalog, a registry that scans the tree for a cart value reaching a file call and reconciles what it finds against the lists in cart.c, so a new one of these cannot be added without somebody noticing. Its --reconcile is quiet enough for the nightly cron the other catalogs use, and it is what turned up seven of the names now on those lists. refs #37623 diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c index d6b50788425..85ef023b500 100644 --- src/hg/hgTracks/hgTracks.c +++ src/hg/hgTracks/hgTracks.c @@ -4384,30 +4384,36 @@ } struct lineFile *lf = NULL; if (strstr(multiRegionsBedUrl,"://")) { lf = lineFileUdcMayOpen(multiRegionsBedUrl, FALSE); if (!lf) { warn("Unable to open [%s] with udc", multiRegionsBedUrl); return FALSE; } *bedDateTime = udcTimeFromCache(multiRegionsBedUrl, NULL); } else { + /* Not a URL, so this is the trash file we wrote the pasted BED to. */ + if (!isServerUserFilePath(multiRegionsBedUrl)) + { + warn("BED custom regions file [%s] not found.", multiRegionsBedUrl); + return FALSE; + } lf = lineFileMayOpen(multiRegionsBedUrl, TRUE); if (!lf) { warn("BED custom regions file [%s] not found.", multiRegionsBedUrl); return FALSE; } *bedDateTime = 0; // touch corresponding .sha1 file to save it from trash cleaner. char multiRegionsBedUrlSha1Name[1024]; safef(multiRegionsBedUrlSha1Name, sizeof multiRegionsBedUrlSha1Name, "%s.sha1", multiRegionsBedUrl); if (fileExists(multiRegionsBedUrlSha1Name)) readAndIgnore(multiRegionsBedUrlSha1Name); } char *line; int lineSize; @@ -8612,31 +8618,31 @@ tg->drawItems = bigDrawWarning; tg->totalHeight = bigWarnTotalHeight; } } } void outCollectionsToJson() /* Output the current collections to the hgTracks JSON block. */ { struct grp *groupList = NULL; char buffer[4096]; safef(buffer, sizeof buffer, "%s-%s", customCompositeCartName, database); char *hubFile = cartOptionalString(cart, buffer); -if (hubFile != NULL) +if (hubFile != NULL && isServerUserFilePath(hubFile)) { char *hubName = hubNameFromUrl(hubFile); struct trackDb *hubTdbs = hubCollectTracks( database, &groupList); struct trackDb *tdb; struct jsonElement *jsonList = NULL; for(tdb = hubTdbs; tdb; tdb = tdb->next) { if (sameString(tdb->grp, hubName)) { if (jsonList == NULL) jsonList = newJsonList(NULL); struct jsonElement *collection = newJsonObject(newHash(4)); jsonObjectAdd(collection, "track", newJsonString(tdb->track)); jsonObjectAdd(collection, "shortLabel", newJsonString(tdb->shortLabel));