CVE-2026-73374 is a stored XSS in a CVE tracking platform where the vulnerability isn't sloppy code—it's the presence of markupsafe.Markup itself. The render_tag_badges filter wraps its output in Markup, telling Jinja 'this is already safe, do not escape.' That's a reasonable pattern for truly static scaffolding, but it creates a hidden contract: every input must be pre-escaped by the caller. The CNA API accepts reference tags from authenticated users, passes them to this filter, and the filter marks them safe. The developer mentally categorized this as 'HTML generator' rather than 'HTML renderer of untrusted content,' and never documented the pre-escaping requirement. This is the ergonomic trap: Markup makes HTML generation look safe while actually disabling Jinja's auto-escaping defense.
The fix—escaping inputs at the point of HTML construction while keeping Markup only for static scaffolding—inverts the safety assumption back to the correct model. Apply markupsafe.escape() to any user-controlled data before it enters HTML construction, not after.
What elevates this beyond a typical stored XSS: the victims are security analysts, CNA members, and infrastructure defenders visiting a security-critical platform. Session compromise here means access to authenticated CNA sessions, links to external databases, and potentially coordinated disclosure workflows. The blast radius isn't a blog comment—it's a trusted security tool.
Audit your codebase for other functions where Markup wraps output that later received untrusted data flow. The commit history likely shows Markup applied as a convenience (silencing template warnings), then untrusted data wired through later by someone who assumed the original developer had a reason. This pattern recurs; the next developer will reach for Markup again the moment they see an unsafe-string warning unless your team explicitly documents the safe/unsafe boundary in the function name or type signature.