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/hgBlat/hgBlat.c src/hg/hgBlat/hgBlat.c index bbde8684329..846a2e42cfd 100644 --- src/hg/hgBlat/hgBlat.c +++ src/hg/hgBlat/hgBlat.c @@ -2865,31 +2865,33 @@ char *pslFile = cartOptionalString(cart, "blatPslFile"); char *faFile = cartOptionalString(cart, "blatFaFile"); /* Use the db/organism the saved search ran against, not the cart's current db (which may have * drifted): the trash PSLs carry that assembly's chrom names, so rendering under any other db * gives broken position and "View alignment" links (hgc "bad input variables"). */ char *savedDb = cartOptionalString(cart, "blatDb"); if (isNotEmpty(savedDb)) { database = savedDb; char *savedOrg = cartOptionalString(cart, "blatOrganism"); if (isNotEmpty(savedOrg)) organism = savedOrg; } cartWebStart(cart, database, "%s (%s) BLAT Results", trackHubSkipHubName(organism), trackHubSkipHubName(database)); -if (pslFile == NULL || faFile == NULL || !fileExists(pslFile)) +if (pslFile == NULL || faFile == NULL || + !isServerUserFilePath(pslFile) || !isServerUserFilePath(faFile) || + !fileExists(pslFile)) printf("<p>These BLAT results are no longer available. Please run a new " "<a href=\"hgBlat\">BLAT search</a>.</p>\n"); else showAliPlaces(pslFile, faFile, NULL, database, gftDna, gftDna, organism, FALSE); cartWebEnd(); } static boolean blatSafeTrashId(char *s) /* TRUE only if s is a bare trash-file basename token (letters, digits, underscore). Because it can * contain no '/', '.' or '..', a path built from it cannot escape the trash directory. */ { if (isEmpty(s)) return FALSE; char *p; for (p = s; *p != '\0'; ++p)