Angular SSR heap OOM during mXSS stabilization, amplified by transient Domino ID indexing
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 35/100
- Issue 类型
- 缺陷
- 描述清晰度
- 需要澄清
- 活跃度
- 活跃
- 技术栈
- angular, node.js, typescript
- 领域
- backend, performance
调研方向
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.
由索引模型根据 Issue 内容生成。
描述
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
- 主要语言
- TypeScript
- 星标
- 101k
- 派生
- 28.1k
- 平均合并
- 2 天 6 小时
- 30 天内合并 PR
- 307
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
angular/angular 的其他 Issue
-
area: docs
难度 2/5 1-3 小时 新手友好度 76/100
-
area: forms forms: signals
难度 2/5 1-3 小时 新手友好度 78/100
-
area: docs gemini-triaged
难度 2/5 1-3 小时 新手友好度 70/100
-
area: forms forms: signals
难度 2/5 1-3 小时 新手友好度 68/100
-
area: docs area: forms
难度 2/5 1-3 小时 新手友好度 76/100
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 70/100
-
难度 2/5 1-3 小时 新手友好度 75/100
mksglu/context-mode#1200 ·
-
难度 2/5 1-3 小时 新手友好度 75/100
jaegertracing/jaeger-ui#4506 ·
-
area:desktop area:ui bug platform:macos
难度 2/5 1-3 小时 新手友好度 75/100
anthropics/claude-code#96687 ·
-
good first issue
难度 1/5 1 小时以内 新手友好度 95/100
AOSSIE-Org/DebateAI#582 · 2 条评论 ·