{"id":"GHSA-f67j-2jqw-jpq7","revision":null,"records":[{"revision":"b2423d37964547b1aee845f3362a509f","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-101895","aliases":[],"title":"Angular SSR: Denial of Service (DoS) via Infinite Loop on Malformed DOCTYPE","description":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.31, 21.2.23, and 22.1.6, the @angular/platform-server DOM emulation parser can enter an infinite synchronous loop when Angular server-side rendering processes attacker-controlled HTML containing an incomplete DOCTYPE that ends with whitespace at end of input. In Domino lib/HTMLParser.js, after_doctype_name_state emits doctype and EOF tokens without advancing nextchar or leaving the fixed-lookahead state, so the scanner repeatedly handles the same EOF marker. A remote unauthenticated attacker can use this condition through server-side HTML parsing paths such as innerHTML binding to consume a Node.js SSR worker at full CPU, starve the event loop, and stop concurrent and subsequent requests. This issue is fixed in versions 20.3.31, 21.2.23, and 22.1.6.","state":0,"publishedAt":"2026-10-14T15:00:14.385+00:00","modifiedAt":"2026-10-14T17:38:10.017+00:00","affected":[{"ecosystem":"Vendor product","name":"angular","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"angular\",\n                    \"product\": \"angular\",\n                    \"versions\": [\n                        {\n                            \"version\": \"<= 19.2.25\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 20.0.0, < 20.3.31\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 21.0.0, < 21.2.23\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 22.0.0, < 22.1.6\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"},{"ecosystem":"Vendor product","name":"platform-server","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"@angular/\",\n                    \"product\": \"platform-server\",\n                    \"versions\": [\n                        {\n                            \"version\": \"<= 19.2.25\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 20.0.0, < 20.3.31\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 21.0.0, < 21.2.23\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 22.0.0, < 22.1.6\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","score":8.7,"severity":"HIGH"}],"references":["https://github.com/angular/angular/security/advisories/GHSA-f67j-2jqw-jpq7","https://github.com/angular/angular/commit/3db26e2544964d07a520836ad01f02f36ec88e25","https://github.com/angular/angular/commit/fc2e8fbc0bda2f5c11585e8a0cbd88c074f5e567","https://github.com/angular/domino/commit/4d97473116d000e3fd4d6f75ec98cbd67576fa6f","https://github.com/angular/angular/releases/tag/v20.3.31","https://github.com/angular/angular/releases/tag/v21.2.23","https://github.com/angular/angular/releases/tag/v22.1.6"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-101895","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-101895","identifiers":["CVE-2026-101895"]},"retained":false,"historicalAffected":[]},{"revision":"b5c61e1c75ac4b92bb9abb39d5b3ed6d","observedAt":"2026-11-09T04:16:01.253+00:00","statement":{"source":"euvd","id":"EUVD-2026-101126","aliases":["CVE-2026-101895","GHSA-f67j-2jqw-jpq7"],"title":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.31, 21.2.23, and 22.1.6, the @angular/platform-server DOM emulation parser can enter an infini…","description":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.31, 21.2.23, and 22.1.6, the @angular/platform-server DOM emulation parser can enter an infinite synchronous loop when Angular server-side rendering processes attacker-controlled HTML containing an incomplete DOCTYPE that ends with whitespace at end of input. In Domino lib/HTMLParser.js, after_doctype_name_state emits doctype and EOF tokens without advancing nextchar or leaving the fixed-lookahead state, so the scanner repeatedly handles the same EOF marker. A remote unauthenticated attacker can use this condition through server-side HTML parsing paths such as innerHTML binding to consume a Node.js SSR worker at full CPU, starve the event loop, and stop concurrent and subsequent requests. This issue is fixed in versions 20.3.31, 21.2.23, and 22.1.6.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","score":8.7,"severity":null}],"references":["https://github.com/angular/angular/security/advisories/GHSA-f67j-2jqw-jpq7","https://github.com/angular/angular/commit/3db26e2544964d07a520836ad01f02f36ec88e25","https://github.com/angular/angular/commit/fc2e8fbc0bda2f5c11585e8a0cbd88c074f5e567","https://github.com/angular/domino/commit/4d97473116d000e3fd4d6f75ec98cbd67576fa6f","https://github.com/angular/angular/releases/tag/v20.3.31","https://github.com/angular/angular/releases/tag/v21.2.23","https://github.com/angular/angular/releases/tag/v22.1.6"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-101126","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Oct 14, 2026, 3:00:14 PM","dateUpdated":"Oct 14, 2026, 5:38:10 PM"},"relatedAdvisories":[],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-101126","identifiers":["EUVD-2026-101126","CVE-2026-101895","GHSA-f67j-2jqw-jpq7"]},"retained":false,"historicalAffected":[]},{"revision":"2c1afcb3fe614436b2a96d682d750086","observedAt":"2026-10-25T04:17:26.915+00:00","statement":{"source":"nvd","id":"CVE-2026-101895","aliases":[],"title":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.31, 21.2.23, and 22.1.6, the @angular/platform-server DOM emulation parser can enter an infini…","description":"Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. Prior to 20.3.31, 21.2.23, and 22.1.6, the @angular/platform-server DOM emulation parser can enter an infinite synchronous loop when Angular server-side rendering processes attacker-controlled HTML containing an incomplete DOCTYPE that ends with whitespace at end of input. In Domino lib/HTMLParser.js, after_doctype_name_state emits doctype and EOF tokens without advancing nextchar or leaving the fixed-lookahead state, so the scanner repeatedly handles the same EOF marker. A remote unauthenticated attacker can use this condition through server-side HTML parsing paths such as innerHTML binding to consume a Node.js SSR worker at full CPU, starve the event loop, and stop concurrent and subsequent requests. This issue is fixed in versions 20.3.31, 21.2.23, and 22.1.6.","state":0,"publishedAt":"2026-10-14T15:17:03.37+00:00","modifiedAt":"2026-10-16T16:00:33.533+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · security-advisories@github.com · Secondary","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","score":8.7,"severity":"HIGH"}],"references":["https://github.com/angular/angular/commit/3db26e2544964d07a520836ad01f02f36ec88e25","https://github.com/angular/angular/commit/fc2e8fbc0bda2f5c11585e8a0cbd88c074f5e567","https://github.com/angular/angular/releases/tag/v20.3.31","https://github.com/angular/angular/releases/tag/v21.2.23","https://github.com/angular/angular/releases/tag/v22.1.6","https://github.com/angular/angular/security/advisories/GHSA-f67j-2jqw-jpq7","https://github.com/angular/domino/commit/4d97473116d000e3fd4d6f75ec98cbd67576fa6f"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-101895","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Awaiting Analysis","weaknesses":["CWE-400","CWE-835"],"productCriteria":[],"sourceDates":{"published":"2026-10-14T15:17:03.370","lastModified":"2026-10-16T16:00:33.533"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-101895","identifiers":["CVE-2026-101895"]},"retained":false,"historicalAffected":[]},{"revision":"68e6b3888bca4f24a19669c95d961e1e","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-f67j-2jqw-jpq7","aliases":["CVE-2026-101895"],"title":"Angular SSR: Denial of Service (DoS) via Infinite Loop on Malformed DOCTYPE","description":"A Denial of Service (DoS) vulnerability exists in `@angular/platform-server`'s DOM emulation parser (`domino`). When processing untrusted user input containing an incomplete DOCTYPE declaration ending with whitespace before EOF (such as `<!DOCTYPE html `), the HTML parser enters an infinite synchronous loop, pegging CPU utilization at 100% and completely freezing the Node.js server process.\n\n### Technical Description\nIn Angular Server-Side Rendering (SSR), `@angular/platform-server` uses `domino` to parse and sanitize HTML bound through template bindings (such as `[innerHTML]`) or manipulated via DOM APIs.\n\nIn Domino's HTML parser (`lib/HTMLParser.js`), tokenizer states that specify fixed lookahead—such as `after_doctype_name_state` (`lookahead = 6`)—rely on the state handler function to explicitly advance the character index pointer (`nextchar`). While branches for whitespace, `>`, and keyword matching advance `nextchar`, the EOF branch (`case -1: // EOF`) emitted doctype and EOF tokens without advancing `nextchar` or transitioning out of the state:\n\n```javascript\ncase -1: // EOF\n  forcequirks();\n  emitDoctype();\n  emitEOF();\n  break;\n```\n\nBecause `nextchar` remained unchanged pointing to the EOF marker character (`\\uFFFF`), the scanner loop (`while (nextchar < numchars)`) repeatedly re-invoked `after_doctype_name_state` with `codepoint = EOF` indefinitely. In Node.js's single-threaded runtime, this synchronous loop starves the event loop entirely.\n\n### Impact & Reachability\n* **Reachability**: The vulnerability is reachable in any Angular SSR application where untrusted user input is bound to `[innerHTML]`, interpolated into markup, or sanitized on the server.\n* **Impact**: Successful exploitation allows an unauthenticated remote attacker to cause an immediate Denial of Service (DoS) by sending a payload containing an incomplete DOCTYPE (e.g., `<!DOCTYPE html `). The Node.js SSR process locks up at 100% CPU and ceases responding to all concurrent and subsequent HTTP requests.\n\n**Proof of Concept:**\n```ts\nimport { Component } from '@angular/core';\n\n@Component({\n  selector: 'app-root',\n  standalone: true,\n  template: `<div [innerHTML]=\"payload\"></div>`,\n})\nexport class AppComponent {\n  // Attacker-controlled input containing an incomplete DOCTYPE ending with whitespace\n  payload = '<!DOCTYPE html ';\n}\n```\n\n### Workarounds\n* Avoid binding untrusted user input directly to `[innerHTML]` in server-rendered templates; use standard text interpolation (`{{ userInput }}`) or `[textContent]` when raw HTML rendering is not required.\n* Validate or sanitize user input before passing it to `[innerHTML]` on the server by stripping or rejecting strings matching `/^<!DOCTYPE/i`.","state":0,"publishedAt":"2026-09-28T21:31:21+00:00","modifiedAt":"2026-09-28T21:45:03.8792043+00:00","affected":[{"ecosystem":"npm","name":"@angular/platform-server","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"22.0.0"},{"kind":"fixed","version":"22.1.6"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"npm","name":"@angular/platform-server","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"21.0.0"},{"kind":"fixed","version":"21.2.23"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"npm","name":"@angular/platform-server","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"20.0.0"},{"kind":"fixed","version":"20.3.31"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"npm","name":"@angular/platform-server","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"last_affected","version":"19.2.25"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V4","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"HIGH"}],"references":["https://github.com/angular/angular/security/advisories/GHSA-f67j-2jqw-jpq7","https://github.com/angular/angular"],"sourceUrl":"https://github.com/advisories/GHSA-f67j-2jqw-jpq7","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-f67j-2jqw-jpq7","identifiers":["GHSA-f67j-2jqw-jpq7","CVE-2026-101895"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-09T10:04:34.0648037+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-09T10:04:34.0648037+00:00","lastSuccessAt":"2026-11-09T10:04:34.2246806+00:00","error":null,"lastVerifiedAt":"2026-11-09T10:04:34.2246841+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-24e6fde7b744113daefb8f6135035fb8a5c69c9617c9c0d40574a0376532ffd3-959e97d06f32ad78d34e1b0ba6a6e5cd74265f5a3f17190fe2a4f93cc705e8ca","complete":true,"records":421341,"lastAttemptAt":"2026-11-09T10:02:25.7011931+00:00","lastSuccessAt":"2026-11-09T10:02:25.6766256+00:00","error":null,"lastVerifiedAt":"2026-11-09T10:02:25.7011931+00:00","snapshotPublishedAt":"2026-11-09T09:30:06+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-994943cd8cb046f49f56409fe0b1d8c6","complete":false,"records":13655,"lastAttemptAt":"2026-11-09T10:16:43.0170247+00:00","lastSuccessAt":"2026-11-09T10:16:43.013+00:00","error":"6 identifier lookups failed; latest failures include HTTP 403. Other identifiers were checked independently.","lastVerifiedAt":"2026-11-09T10:16:43.013+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13701,"expectedIdentifiers":13707,"failedIdentifiers":6},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-09T10:04:34.0648037+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-09T10:04:34.0648037+00:00","lastSuccessAt":"2026-11-09T10:04:34.2253534+00:00","error":null,"lastVerifiedAt":"2026-11-09T10:04:34.2253535+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-4dc74a26d06148ffa8eb6751d602315d","complete":true,"records":13667,"lastAttemptAt":"2026-11-09T10:04:35.2758607+00:00","lastSuccessAt":"2026-11-09T10:04:35.272+00:00","error":null,"lastVerifiedAt":"2026-11-09T10:04:35.272+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13707,"expectedIdentifiers":13707,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-980593e6977a6d1b4fb1eed5a1ffe88a468736f89f0a06f710924ad59132c023","complete":true,"records":9914,"lastAttemptAt":"2026-11-09T10:04:28.5294921+00:00","lastSuccessAt":"2026-11-08T11:07:07.068788+00:00","error":null,"lastVerifiedAt":"2026-11-09T10:04:28.5294921+00:00","snapshotPublishedAt":"2026-11-08T11:02:46+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-fde804134ecdda0ddd5ff5c26ee1fff5a6fa659311f7ef2e51c6ad54964db0e2","complete":true,"records":1971,"lastAttemptAt":"2026-11-09T10:02:25.7473895+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-09T10:02:25.7473895+00:00","snapshotPublishedAt":"2026-11-06T18:17:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-747b24005f13ffe3f133ae77dfb12ae3145f2c7aed5cfebb91eb943ceb4daeb6","complete":true,"records":3060,"lastAttemptAt":"2026-11-09T10:04:34.0336984+00:00","lastSuccessAt":"2026-11-09T10:04:33.8957851+00:00","error":null,"lastVerifiedAt":"2026-11-09T10:04:34.0336984+00:00","snapshotPublishedAt":"2026-11-09T10:03:05+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-e6e6ac3eaece246ff08884368fe1dc99d4d393571e77c126c8f4d38d66697688","complete":true,"records":231297,"lastAttemptAt":"2026-11-09T10:04:28.3938244+00:00","lastSuccessAt":"2026-11-09T10:04:27.0059369+00:00","error":null,"lastVerifiedAt":"2026-11-09T10:04:28.3938244+00:00","snapshotPublishedAt":"2026-11-09T09:33:10+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}