056f7f77ed59453f48a8821b62526aef2457fc25
max
  Fri Sep 18 05:12:31 2026 -0700
hgSearch: htmlEncode maneStatus/maneProtAcc before writing to JSON

#Preview2 week - bugs introduced now will need a build patch to fix
Found by AI code review: these fields were sent to the client
unescaped while the sibling posName field was htmlEncode'd, even
though hgSearch.js inserts both into innerHTML the same way.

diff --git src/hg/cgilib/cartJson.c src/hg/cgilib/cartJson.c
index 0a7ca05d62c..56fc9ebbb00 100644
--- src/hg/cgilib/cartJson.c
+++ src/hg/cgilib/cartJson.c
@@ -159,35 +159,35 @@
                     maneLookup = maneLookupOpen(db, &tdbList);
                     maneLookupTimeMs += clock1000() - maneOpenT0;
                     maneLookupAttempted = TRUE;
                     }
                 if (maneLookup != NULL)
                     {
                     struct slName *protAccList = slNameListFromString(pos->name, '/');
                     long maneT0 = clock1000();
                     char *maneProtAcc = NULL;
                     char *maneStatus = maneStatusForRegion(maneLookup, pos->chrom,
                                                            pos->chromStart, pos->chromEnd,
                                                            protAccList, &maneProtAcc);
                     maneLookupTimeMs += clock1000() - maneT0;
                     if (maneStatus != NULL)
                         {
-                        jsonWriteString(jw, "maneStatus", maneStatus);
+                        jsonWriteString(jw, "maneStatus", htmlEncode(maneStatus));
                         // the single accession that is the actual MANE transcript, since
                         // pos->name/posName above may be a "/"-joined group of transcripts
                         // that all share this genomic footprint
-                        jsonWriteString(jw, "maneProtAcc", maneProtAcc);
+                        jsonWriteString(jw, "maneProtAcc", htmlEncode(maneProtAcc));
                         }
                     slFreeList(&protAccList);
                     }
                 }
             if (pos->description)
                 {
                 stripString(pos->description, "\n");
                 jsonWriteString(jw, "description", stripAnchor(pos->description));
                 }
             jsonWriteObjectEnd(jw); // end one match
             }
         jsonWriteListEnd(jw); // end matches
         if (table->searchTime >= 0)
             jsonWriteNumber(jw, "searchTime", table->searchTime);
         jsonWriteObjectEnd(jw); // end one table