56fec2823d2419eb9395bed6f2b56dec2c1daceb max Fri Aug 28 02:02:18 2026 -0700 Escape nodeName in variantPathPrint (XSS), found by automated code review htmlEncode vpn->nodeName before printing in variantPathPrint() to close XSS gap. The node name can be a user-uploaded sample ID (FASTA/VCF), making this a reachable vulnerability of the same class the parent commit closes in other spots. diff --git src/hg/hgPhyloPlace/phyloPlace.c src/hg/hgPhyloPlace/phyloPlace.c index c12f47b7476..ec370502c96 100644 --- src/hg/hgPhyloPlace/phyloPlace.c +++ src/hg/hgPhyloPlace/phyloPlace.c @@ -805,31 +805,31 @@ if (startsWith(USHER_NODE_PREFIX, nodeName)) nodeName += strlen(USHER_NODE_PREFIX); return isAllDigits(nodeName) && (minNewNode <= 0 || (atoi(nodeName) < minNewNode)); } static void variantPathPrint(struct variantPathNode *variantPath) /* Print out a variantPath; print nodeName only if non-numeric * (i.e. a sample ID not internal node) */ { struct variantPathNode *vpn; for (vpn = variantPath; vpn != NULL; vpn = vpn->next) { if (vpn != variantPath) printf(" > "); if (!isInternalNodeName(vpn->nodeName, 0)) - printf("%s: ", vpn->nodeName); + printf("%s: ", htmlEncode(vpn->nodeName)); struct singleNucChange *snc; for (snc = vpn->sncList; snc != NULL; snc = snc->next) { if (snc != vpn->sncList) printf(", "); printf("%c%d%c", snc->parBase, snc->chromStart+1, snc->newBase); } } } static void displayVariantPath(struct variantPathNode *variantPath, char *sampleId) /* Display mutations on the path to this sample. */ { printf("
Mutations along the path from the root of the phylogenetic tree to %s:\n", htmlEncode(sampleId)); // uploaded sample name, escape (XSS)