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/blatShare.c src/hg/lib/blatShare.c
index 1908f09aacf..73aa37e8e4a 100644
--- src/hg/lib/blatShare.c
+++ src/hg/lib/blatShare.c
@@ -4,30 +4,31 @@
  * server-file security check. */
 
 /* Copyright (C) 2024 The Regents of the University of California
  * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */
 
 #include "common.h"
 #include "localmem.h"
 #include "psl.h"
 #include "bbiFile.h"
 #include "bigBed.h"
 #include "bigPsl.h"
 #include "cart.h"
 #include "chromAlias.h"
 #include "hgConfig.h"
 #include "portable.h"
+#include "trashDir.h"
 #include "blatShare.h"
 
 struct psl *pslListFromBigPslFile(char *bbFileName)
 /* Read every alignment out of a bigPsl bigBed file into a psl list, in query-display order.
  * Used to rebuild the Table view for a shared link from the durable custom track. */
 {
 struct bbiFile *bbi = bigBedFileOpenAlias(bbFileName, chromAliasFindAliases);
 struct lm *lm = lmInit(0);
 struct psl *pslList = NULL;
 struct bbiChromInfo *chrom, *chromList = bbiChromList(bbi);
 for (chrom = chromList; chrom != NULL; chrom = chrom->next)
     {
     struct bigBedInterval *bb, *ivList = bigBedIntervalQuery(bbi, chrom->name, 0, chrom->size, 0, lm);
     for (bb = ivList; bb != NULL; bb = bb->next)
         {
@@ -92,23 +93,19 @@
 bbiFileClose(&bbi);
 return result;
 }
 
 char *blatFindPinnedBigPsl(struct cart *cart)
 /* Return a cloned path to the BLAT bigPsl bigBed that hgc's buildBigPsl pinned in the cart
  * (blatLastBigBed), or NULL.  Reading the pinned value is unambiguous even when the cart holds
  * several BLAT custom tracks from earlier searches.  A shared session (?u=&s=) can carry an arbitrary
  * value here, so only ever accept a local file the server itself placed under its trash dir, or under
  * the durable session-data dir (where a saved session's trash files are moved) - never a remote URL
  * or an arbitrary local path.  This is the trash/sessionData allow-list from isValidBigDataUrl(). */
 {
 char *f = cartOptionalString(cart, "blatLastBigBed");
 if (f == NULL)
     return NULL;
-char *sessionDataDir = cfgOption("sessionDataDir");
-char *sessionDataDirOld = cfgOption("sessionDataDirOld");
-if (startsWith(trashDir(), f) ||
-    (isNotEmpty(sessionDataDir) && startsWith(sessionDataDir, f)) ||
-    (isNotEmpty(sessionDataDirOld) && startsWith(sessionDataDirOld, f)))
+if (isTrashOrSessionDataPath(f))
     return cloneString(f);
 return NULL;
 }