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/lib/trackHub.c src/hg/lib/trackHub.c index 550425a9a12..ba8f9aaf229 100644 --- src/hg/lib/trackHub.c +++ src/hg/lib/trackHub.c @@ -1597,31 +1597,31 @@ if (isEmpty(s)) return NULL; char *sp = skipToSpaces(s); int len = (sp != NULL) ? (sp - s) : (int)strlen(s); return cloneStringZ(s, len); } boolean quickLiftHubRemoveTrack(struct cart *cart, char *sourceDb, char *trackName) /* Remove a track stanza from the quickLift hub file for sourceDb, along with * any descendant stanzas (transitively) whose parent is being removed. * Returns TRUE if at least one stanza was removed. */ { char buffer[4096]; safef(buffer, sizeof buffer, "%s-%s", quickLiftCartName, sourceDb); char *filename = cartOptionalString(cart, buffer); -if (filename == NULL) +if (filename == NULL || !isServerUserFilePath(filename)) return FALSE; struct lineFile *lf = lineFileMayOpen(filename, TRUE); if (lf == NULL) return FALSE; char *bareName = trackHubSkipHubName(trackName); struct dyString *header = dyStringNew(0); struct quickLiftStanza *stanzaList = NULL; struct quickLiftStanza *cur = NULL; char *line; int lineSize; /* Pass 1: read the file into a header + list of stanzas, recording each * stanza's name and (if any) parent. */