From 0133d0a85136a1ad21c6bab89f84937f60722b7f Mon Sep 17 00:00:00 2001 From: appsechq-brian Date: Wed, 22 Apr 2026 15:14:23 -0400 Subject: [PATCH] Fix JUnit XML attribute escaping (use quoteattr) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Findings whose message text contained a double quote produced malformed XML attributes that Azure Pipelines' PublishTestResults@2 rejected with "'Secure' is an unexpected token. Expecting whitespace" and the Tests tab failed to populate. xml.sax.saxutils.escape() only handles &, <, >. quoteattr() additionally escapes " and returns the value wrapped in quotes — the canonical way to build XML attribute values. Verified end-to-end in the AppSecHQ/vectorvictor publish-results pipeline against a run with 69 findings; Tests tab now populates cleanly. --- scripts/cycode-json-to-junit.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/cycode-json-to-junit.py b/scripts/cycode-json-to-junit.py index 9ad7ee7..66751bc 100755 --- a/scripts/cycode-json-to-junit.py +++ b/scripts/cycode-json-to-junit.py @@ -13,7 +13,7 @@ import json import sys -from xml.sax.saxutils import escape +from xml.sax.saxutils import escape, quoteattr def extract_detections(data): @@ -61,10 +61,13 @@ def main(src: str, dst: str) -> int: name = f"{path}:{line}" if line else path detail = json.dumps(d, indent=2, default=str) cdata = detail.replace("]]>", "]]]]>") - out.append(f' ') + # Use quoteattr (returns the value wrapped in quotes with ", &, <, > + # escaped). Plain escape() doesn't handle " — any finding message + # containing a double quote breaks PublishTestResults@2 parsing. + out.append(f' ') out.append( - f' ' + f' ' ) out.append(" ")