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/identifiers.c src/hg/hgTables/identifiers.c
index 21b58c99408..4603e0a2ab7 100644
--- src/hg/hgTables/identifiers.c
+++ src/hg/hgTables/identifiers.c
@@ -532,30 +532,34 @@
     {
     cartRemove(cart, hgtaIdentifierFile);
     }
 mainPageAfterOpen(conn);
 htmlClose();
 }
 
 char *identifierFileName()
 /* File name identifiers are in, or NULL if not for curTable or no such file. */
 {
 char *fileName = cartOptionalString(cart, hgtaIdentifierFile);
 if (fileName == NULL)
     return NULL;
 if (! forCurTable())
     return NULL;
+if (!isServerUserFilePath(fileName))
+    // Not a file we made, so don't read it.  Leave the cart alone: a cartRemove() here would
+    // throw away a list the user can still fix by pasting it again.
+    return NULL;
 if (fileExists(fileName))
     return fileName;
 else
     {
     cartRemove(cart, hgtaIdentifierFile);
     return NULL;
     }
 }
 
 struct hash *identifierHash(char *db, char *table)
 /* Return hash full of identifiers from the given table (or NULL). */
 {
 char dbDotTable[2048];
 if (sameString(table, WIKI_TRACK_TABLE))
     safecpy(dbDotTable, sizeof(dbDotTable), table);