Skip to content

SourceHut Had an XSS Bug Hiding in Build Logs for 4.5 Years

Karify98 & Amy ๐ŸŒธยท
Cover Image for SourceHut Had an XSS Bug Hiding in Build Logs for 4.5 Years

A Polish security researcher went looking at SourceHut's build log page because the scrolling annoyed him โ€” and walked away with a bug capable of hijacking admin accounts on the entire platform. The flaw sat unnoticed for four and a half years, now tracked as CVE-2026-92973.

What happened

SourceHut (sr.ht) โ€” the minimalist, JavaScript-averse Git hosting platform popular with open-source projects โ€” uses the Python library ansi2html to convert build log output (full of ANSI color codes) into HTML for the web. That library also supports OSC 8, the terminal escape sequence standard for clickable hyperlinks. Its parser doesn't sanitize that input properly.

The result: a carefully crafted escape sequence, once printed to a log, turns into an <a> tag carrying onfocus="alert(...)" plus autofocus โ€” JavaScript that fires the moment someone opens the log page, no click required. It's a textbook XSS, delivered through an unusual door: the build log.

Why this one is worse than typical XSS

The build log page on builds.sr.ht already has a CSRF token sitting in the DOM. An attacker doesn't need to steal it โ€” the script just reads it and resubmits the "Resubmit build" form on the victim's behalf. If the victim is an admin, the script can grant admin rights to the attacker's own account. Worse, sr.ht's own build workers carry deploy keys, meaning an attacker could theoretically reach the platform's core infrastructure.

No paid account is needed to trigger it, either. Sending a patch to a public mailing list with CI enabled โ€” or controlling any remote resource that ends up printed to the log โ€” is enough to plant the payload. Anyone who opens that log page afterward gets hit.

  • Attack vector: network, no account required (PR:N under CVSS 4.0)
  • User interaction: passive โ€” just opening the page with JavaScript on
  • Scope: wormable โ€” a compromised victim can spread the payload further through their own build logs

The timeline

The bug was introduced into ansi2html upstream in a commit dated 2021-09-03, then quietly shipped in the Alpine Linux package SourceHut uses to build its own infrastructure starting in early 2022. builds.sr.ht carried the flaw for nearly its entire 4.5-year existence before anyone caught it.

The researcher reported it to SourceHut's security team in early August 2026, and founder Drew DeVault shipped a mitigation โ€” auto-sanitizing ansi2html's output โ€” just three days later. Fixing it properly upstream took much longer: ansi2html lives under PyContribs, a group dedicated to keeping abandoned Python packages alive, and one of its two main maintainers never responded. The official fix, version 1.9.4, didn't land until 2026-09-02 โ€” over a month after the initial report.

There's a fitting irony here: ansi2html is one of the projects referenced in xkcd's famous comic about "a project some random person in Nebraska has been thanklessly maintaining since 2003." This time, the joke turned into a real security incident.

What this means for developers

  • Running SourceHut: patch immediately โ€” both builds.sr.ht (>= 0.105.1) and ansi2html (>= 1.9.4) have fixes. Check old build logs for unusual โ›]8;;... sequences as an indicator of compromise
  • Self-hosting CI that renders ANSI logs as HTML: anything a build worker prints โ€” including error output and third-party dependency logs โ€” is untrusted input and needs sanitizing before it hits a browser, even if it "just" looks like colored text
  • Maintaining a small package with large downstream dependents: the ansi2html story is a real-world supply chain lesson โ€” a seemingly harmless formatting utility can become the doorway into an entire CI platform
  • CSP as a forgotten defense layer: SourceHut still relies on inline scripts on the log page, which makes a stricter Content-Security-Policy harder to enforce โ€” a common blind spot for internal dashboards that don't get much security attention

SourceHut built its reputation on minimalism and avoiding JavaScript wherever possible โ€” yet the one small JS feature it kept, auto-scrolling logs, turned out to be exactly where the vulnerability surfaced. The lesson isn't new, but it holds up: the attack surface rarely sits where you expect. It sits where nobody thought to check.


Content assisted by AI (Amy ๐ŸŒธ). Reviewed by the author.

Related Posts