Angular SSR heap OOM during mXSS stabilization, amplified by transient Domino ID indexing
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Accessibilité débutants
- 35/100
- Type d'issue
- Bug
- Clarté
- À clarifier
- Activité
- Active
- Stack technique
- angular, node.js, typescript
- Domaine
- backend, performance
Piste de recherche
Start in core / platform-server and the bundled Domino integration, then reproduce the linked proof of concept while comparing repeated id attributes with the xx control. Done means the reported SSR cases no longer exhaust the Node.js heap, with coverage for the mXSS stabilization and temporary-document behavior described here.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Which @angular/* package(s) are the source of the bug?
core / platform-server (bundled Domino)
Is this a regression?
No
Description
Angular SSR can exhaust the Node.js heap when HTML rendered through a normal [innerHTML] binding contains a specific combination of active-formatting elements and repeated id attributes.
Example:
import { Component } from "@angular/core";
@Component({
selector: "app-root",
template: `<div [innerHTML]="content"></div>`,
})
export class App {
readonly content = attackerControlledHtml;
}
On the server, Angular parses the value into an inert Domino document as part of HTML sanitization. For the minimized input, the sanitizer stabilization path performs multiple fragment parses.
During each parse, Domino maintains Document.byId / MultiId even though the document is only a temporary document used to build a fragment.
With the minimized candidate, the parser creates a large reconstructed DOM and adds more than 100k transient ID-index memberships before those nodes are moved out of the temporary document.
An equal-byte control changes only the attribute name from id to xx.
candidate: repeated id attributes
control: repeated xx attributes
Both inputs have the same size and produce the same element/attribute topology and serialization size, but only the id version enters Domino's ID index.
In the original 256 MiB validation, the 3,988-byte id candidate terminated all five workers:
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
I also tested larger heap limits with payloads calibrated for each limit:
| V8 old space | Request body | xx control |
id candidate |
|---|---|---|---|
| 256 MiB | 3,988 B | 5/5 healthy (original run; 4/5 on repeat) | 5/5 fatal V8 OOM |
| 512 MiB | 6,493 B | 3/3 HTTP 200 + healthy worker | 3/3 fatal V8 OOM |
| 1,024 MiB | 11,431 B | 3/3 HTTP 200 + healthy worker | 3/3 fatal V8 OOM |
More context : https://issuetracker.google.com/u/1/issues/563071374
Follow-up: two contributing memory costs
Further testing shows that Domino's temporary ID index is an amplifier, but not the only reason this reaches the heap limit.
Active-formatting reconstruction already creates a large DOM from the short input. During Angular's mXSS stabilization loop, the previous inert template also remains alive while the next fragment is parsed.
| Build | Request body | xx OOM |
id OOM |
|---|---|---|---|
| Original, repeat | 3,988 B | 1/5 | 5/5 |
| Lazy Domino ID index only | 3,988 B | 0/10 | 1/10 |
| Early mXSS template cleanup only | 3,988 B | 0/5 | 0/5 |
The lazy ID-index change greatly reduces the id failures, while clearing the previous inert template removes the OOM at this size in my tests.
Larger inputs can still exhaust the heap, including inputs without id. I haven't rerun the 512 MiB and 1,024 MiB cases with these changes.
See: https://github.com/SkyZeroZx/angular-ssr-mxss-domino-oom-poc
- Langage dominant
- TypeScript
- Étoiles
- 101k
- Forks
- 28.1k
- Merge moyen
- 2 j 6 h
- PR mergées (30 j)
- 307
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de angular/angular
-
area: docs
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
-
area: forms forms: signals
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
-
area: docs gemini-triaged
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
-
area: forms forms: signals
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
-
area: docs area: forms
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
Toutes les issues de angular/angular
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
mksglu/context-mode#1200 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
jaegertracing/jaeger-ui#4506 ·
-
area:desktop area:ui bug platform:macos
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
anthropics/claude-code#96687 ·
-
good first issue
Difficulté 1/5 Moins d'une heure Accessibilité débutants 95/100
AOSSIE-Org/DebateAI#582 · 2 commentaires ·