03550a41a3b40299ba1405770fdf548dd48a63a7
braney
  Mon Apr 13 15:51:11 2026 -0700
Deduplicate and htmlEncode alias list in printAliases() refs #29201

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index 10f38be4c45..e383b57baf8 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -8837,52 +8837,57 @@
     puts(" <button id='hgtIgv' type='button' "
             "title='Add an IGV.js window below the UCSC Browser, to open files from "
             "your local harddisk or server' >Add IGV Tracks</button>");
     //jsInline("document.getElementById('hgtIgv').addEventListener('click', onIgvClick);");
     }
 
 }
 
 static void printAliases(char *nativeName, char *displayName)
 /* Print out the alternative names for this sequence next to the position. */
 {
 struct slName *aliases = chromAliasFindAliases(nativeName);
 if (aliases == NULL)
     return;
 
+slSort(&aliases, slNameCmp);
+slUniqify(&aliases, slNameCmp, slNameFree);
+
 // Build comma-separated list of aliases, skipping the display name and native name
 struct dyString *dy = dyStringNew(256);
 struct slName *a;
 for (a = aliases; a != NULL; a = a->next)
     {
     if (isEmpty(a->name))
         continue;
     if (sameString(a->name, displayName) || sameString(a->name, nativeName))
         continue;
     if (dy->stringSize > 0)
         dyStringAppend(dy, ", ");
     dyStringAppend(dy, a->name);
     }
 
 if (dy->stringSize == 0)
     {
     dyStringFree(&dy);
     return;
     }
 
+char *encoded = htmlEncode(dy->string);
 printf("<span id='chromAliases' title='Also known as: %s'>"
-       "<a>&#9432; Aliases</a></span>", dy->string);
+       "<a>&#9432; Aliases</a></span>", encoded);
+freeMem(encoded);
 dyStringFree(&dy);
 }
 
 
 unsigned getParaLoadTimeout()
 // get the parallel load timeout in seconds (defaults to 90)
 {
 char *paraLoadTimeoutStr = cartOptionalString(cart, "parallelFetch.timeout");
 if (paraLoadTimeoutStr == NULL)
     paraLoadTimeoutStr = cfgOptionDefault("parallelFetch.timeout", "90");  // wait up to default 90 seconds.
 
 unsigned paraLoadTimeout = sqlUnsigned(paraLoadTimeoutStr);
 
 return paraLoadTimeout;
 }