Skip to content
Security & Trust

One unfinished HTML tag can freeze an Angular SSR server, GitHub advisory says

The parser that cleans untrusted input is the component that hangs, and a single-threaded runtime spreads the damage.

W
WebPulse Newsroom
AI-assisted · 4 min read
Share on X LinkedIn
One unfinished HTML tag can freeze an Angular SSR server, GitHub advisory says

Photo: https://kaboompics.com/ / Pexels

Key finding

CPU utilisation when the loop triggers: 100% (Source: GitHub Advisory Database, GHSA-f67j-2jqw-jpq7 (September 28, 2026))

When the sanitiser is the weak point

Teams add a sanitiser to make untrusted input safe. This week's advisory describes a case where the sanitising step is what stops the server. The lesson is that protective code is still code, and a flaw in it can take down the service it guards.

The GitHub Advisory Database, in an entry published September 28, 2026 (GHSA-f67j-2jqw-jpq7), describes a denial-of-service flaw in the DOM emulation parser, called domino, used by @angular/platform-server. When the parser receives an incomplete DOCTYPE declaration that ends in whitespace just before the end of the input, such as

100%
CPU utilisation when the loop triggers
Source: GitHub Advisory Database, GHSA-f67j-2jqw-jpq7 (September 28, 2026)

Why one request becomes everyone's outage

The advisory traces the fault to a missing step. In one parser state, the branch that handles end-of-input emitted its tokens but never moved the read position forward or left the state. The scanner kept re-reading the same end marker indefinitely.

A bug like this in one request handler would be an inconvenience. Here it lands in a single-threaded runtime, where the advisory says the synchronous loop starves the event loop. The affected process stops answering all concurrent and subsequent HTTP requests. A single attacker payload therefore reaches every visitor connected to that process, not only the visitor who sent it. The advisory describes the attacker as unauthenticated and remote.

For a budget-holder, this changes how the risk should be sized. The cost of the flaw is not a bad page for one user. It is the availability of whatever that server process serves: checkout, sign-in, account pages, or anything else rendered on the server.

Reachability is the question that matters

According to the advisory, exposure turns on one condition: whether text controlled by a visitor can reach the server-side HTML parser, whether through an [innerHTML] binding, insertion into markup, or server-side sanitising. Applications that never route user-controlled strings down those paths fall outside that description.

This is where WebPulse data helps only in part. In its September 2026 scan of the Tranco top 10,000 domains, WebPulse detected Angular on 155 of the 2,491 sites where a platform was identified, or 6.2%. Detection cannot show whether a site renders on the server or binds user input to [innerHTML], so it says nothing about how many of those sites are exposed.

155 (6.2%)
Sites with Angular detected, of 2,491 with a platform identified
Source: WebPulse scan of Tranco top-10,000 domains (September 2026)

NIST NVD records, matched by WebPulse on September 29, 2026, list 24 CVEs for Angular, 23 of them in the last 12 months. That is a count of published entries, not a measure of how exposed any one deployment is. It does show the framework's disclosure stream is active enough that patch routines need to be routine.

23
Angular CVEs in NIST NVD, last 12 months (24 total)
Source: NIST NVD via WebPulse CVE profiles (refreshed September 29, 2026)

Questions to put to your team

First, do we run Angular server-side rendering, and which public pages or APIs pass user-supplied text into [innerHTML] or server-side sanitisation? Second, what does the advisory list as the fixed version, and when will our build pick it up? The advisory text supplied here does not state one, so the team should read the entry directly.

Third, if a server process locked up, how quickly would we detect it and restart it? A frozen process may keep accepting connections while answering none, so a health check that only tests that the process is running would miss it. Fourth, is there a way to isolate rendering so that one stuck process does not take all traffic with it?

The advisory also offers interim steps. Where raw HTML is not needed, render user text through plain interpolation or [textContent]. Where it is needed, reject or strip strings matching /^

The wider point is that availability depends on every layer beneath your own code, including the ones that exist to keep input safe. Ask where in your stack a single malformed string can stop a process that serves everyone.

Produced by the WebPulse Newsroom with AI assistance from the original reporting credited below, and checked against that source by our editorial review. How we use AI.
Original reporting: GitHub Advisory Database.

Share this insight