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/hgTables/genomeSpace.c src/hg/hgTables/genomeSpace.c
index 9495d8c9fbe..45c66a240a9 100644
--- src/hg/hgTables/genomeSpace.c
+++ src/hg/hgTables/genomeSpace.c
@@ -596,30 +596,34 @@
         // done waiting for child.
 
     }
 
 }
 
 
 void gsSendToDM()
 /* upload the generated file to DM */
 {
 // This is now run via fork/exec as a separate background process.
 
 char *trashFileName = cartUsualString(cart, "gsTemp", "");
 char *fileName = cartUsualString(cart, hgtaOutFileName, "");
 
+/* The upload sends this file to a remote service, so be sure it is one we made. */
+if (!isServerUserFilePath(trashFileName))
+    errAbort("Nothing to upload.");
+
 // adjust upload name based on compression and existing extension
 char *compressType = cartUsualString(cart, hgtaCompressType, textOutCompressNone);
 
 if (!(isEmpty(compressType) || sameWord(compressType, textOutCompressNone)))
     {
     char *suffix = getCompressSuffix(compressType);
     if (!endsWith(fileName, suffix))
 	fileName = addSuffix(fileName, suffix);
     }
 
 
 off_t fSize = fileSize(trashFileName);
 
 
 char *gsToken = cartUsualString(cart, "gsToken", NULL);