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