{"vulnerability": "CVE-2026-69151", "sightings": [{"uuid": "02150ce7-9740-415e-8045-30438836d805", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-69151", "type": "seen", "source": "https://bsky.app/profile/stackflag.bsky.social/post/3ms6xhvahdl2o", "content": "CVE-2026-69151 - compiler\nA security issue in Angular's internationalization (i18n) feature allows hackers to inject malicious JavaScript code into web pages. This can happen if an attacker controls\u2026\n\nToo many irrelevant or confusing CVEs? Use stackflag.com\n\n#compiler #angular #npm #CVE #infosec", "creation_timestamp": "2026-08-03T16:52:06.541925Z"}, {"uuid": "cdfb620f-277f-43c0-91e2-63bd0bc2361b", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-69151", "type": "seen", "source": "https://bsky.app/profile/cve.skyfleet.blue/post/cpivbdhgtqa6k", "content": "CVE-2026-69151 - Angular i18n: Cross-Site Scripting (XSS) via event-handler attributes\nCVE ID : CVE-2026-69151\n \n Published : Aug. 3, 2026, 5:16 p.m. | 41\u00a0minutes ago\n \n Description : Angular is a development platform for building mobile and desktop web applications using Type...", "creation_timestamp": "2026-08-03T18:20:14.070826Z"}, {"uuid": "6058a6b7-4a95-44d0-b666-274527705da6", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-69151", "type": "seen", "source": "https://gist.github.com/alon710/bdd530b55ab23396bc2ee2dc380962dc", "content": "# CVE-2026-69151: CVE-2026-69151: Stored Cross-Site Scripting (XSS) in Angular Compiler i18n Pipeline via Event-Handler Attributes\n\n&gt; **CVSS Score:** 7.6\n&gt; **Published:** 2026-08-03\n&gt; **Full Report:** https://cvereports.com/reports/CVE-2026-69151\n\n## Summary\nA high-severity security vulnerability has been identified within the Angular compiler's internationalization (i18n) metadata collection and translation pipeline. Angular implements strict defenses against client-side execution injection by validating standard attribute and property bindings. However, when parsing elements containing both i18n translation attributes and inline event-handler elements (such as `i18n-onerror`), the compiler failed to assert the safety of the target attribute. Consequently, compromised or untrusted localization translation source files can supply arbitrary JavaScript payloads that replace static event-handler bindings. This arbitrary code is compiled directly into the localized build bundle and executed dynamically by the web browser, bypassing runtime sanitization, security checks, and standard binding constraints.\n\n## TL;DR\nAn input validation flaw in the Angular compiler's i18n translation metadata pipeline enables unauthenticated stored Cross-Site Scripting (XSS) when utilizing untrusted translation assets. Attackers who compromise translation databases or localization files can inject arbitrary JavaScript executable payloads into translated attributes like `i18n-onerror`. Standard Angular runtime property-binding security validations fail to catch this injection because the malicious payloads are rendered as static attributes in the compiled HTML document, enabling full client-side session compromise.\n\n## Exploit Status: POC\n\n## Technical Details\n\n- **Vulnerability Type**: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')\n- **Attack Vector**: Network / Content Supply Chain Injection\n- **Attack Complexity**: Low (No special conditions required)\n- **Authentication Requirements**: None (Requires access to influence external translation resources)\n- **CVSS v4.0 Base Score**: 7.6 (High)\n- **Exploit Status**: Proof-of-Concept (No known active exploitation in the wild)\n- **CISA KEV Status**: Not Listed\n\n## Affected Systems\n\n- Angular compiler (@angular/compiler)\n- Angular core runtime (@angular/core)\n- **@angular/compiler**: &lt; 20.3.27 (Fixed in: `20.3.27`)\n- **@angular/compiler**: &gt;= 21.0.0-next.0, &lt; 21.2.19 (Fixed in: `21.2.19`)\n- **@angular/compiler**: &gt;= 22.0.0-next.0, &lt; 22.0.1 (Fixed in: `22.0.1`)\n- **@angular/core**: &lt; 20.3.27 (Fixed in: `20.3.27`)\n- **@angular/core**: &gt;= 21.0.0-next.0, &lt; 21.2.19 (Fixed in: `21.2.19`)\n- **@angular/core**: &gt;= 22.0.0-next.0, &lt; 22.0.1 (Fixed in: `22.0.1`)\n\n## Mitigation\n\n- Upgrade Angular compiler and core libraries to patched versions (20.3.27, 21.2.19, or 22.0.1)\n- Audit existing HTML templates to ensure event handlers are never marked for translation via i18n-on* attributes\n- Treat translation metadata files (XLF, XLIFF, JSON) as high-risk assets and enforce strict code review pipelines\n- Enforce a rigorous Content Security Policy (CSP) that bans the 'unsafe-inline' script directive\n\n**Remediation Steps:**\n1. Open the project package.json file and identify the versions of @angular/compiler and @angular/core.\n2. Execute the update command matching your current release branch (e.g., 'npm install @angular/core@20.3.27 @angular/compiler@20.3.27' or corresponding yarn/pnpm equivalent).\n3. Configure static analysis linter rules to flag patterns matching i18n-on* attributes in template HTML structures.\n4. Validate the build logs post-upgrade to confirm that any accidental event-handler translation directives throw compile-time exceptions.\n\n## References\n\n- [NVD CVE Record - CVE-2026-69151](https://www.cve.org/CVERecord?id=CVE-2026-69151)\n- [GitHub Security Advisory GHSA-jj27-h5hq-8x99](https://github.com/angular/angular/security/advisories/GHSA-jj27-h5hq-8x99)\n- [Angular Git Core Fix Commit](https://github.com/angular/angular/commit/6c41f5ca01c0ae045fc7d929b72853a11eb55865)\n- [Angular Git Follow-up Refinement Commit](https://github.com/angular/angular/commit/417a4071a776464d549509ed3aec121dbd2fda5e)\n\n\n---\n*Generated by [CVEReports](https://cvereports.com/reports/CVE-2026-69151) - Automated Vulnerability Intelligence*", "creation_timestamp": "2026-08-03T19:31:37.187220Z"}, {"uuid": "30cb15fb-7ceb-40ef-956a-ac8da0a465ed", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-69151", "type": "seen", "source": "https://bsky.app/profile/stackflag.bsky.social/post/3mschryfjmu2l", "content": "CVE-2026-69151 - angular.js\nPrior versions of Angular's compiler allowed a malicious translation file to inject executable JavaScript code into web applications. This could potentially\u2026\n\nToo many irrelevant or confusing CVEs? Use stackflag.com\n\n#angularjs #canonical #UbuntuPro1604LTS #CVE #infosec", "creation_timestamp": "2026-08-05T02:22:04.349661Z"}, {"uuid": "4373b950-7ce8-401d-9488-fb55036ec221", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-69151", "type": "seen", "source": "https://gist.github.com/djlan/14b1946c39d5ba5605dfec06e037e317", "content": "## \u8fd9\u4e2a PR \u60f3\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898\uff1f\n\n**\u6807\u9898\uff1a** [SECURITY] bump Angular from 21.2.17 to 21.2.19 in /sample/angular-host-app\n\n**\u4e00\u53e5\u8bdd\u603b\u7ed3\uff1a** \u5c06 `sample/angular-host-app` \u4f7f\u7528\u7684\u4e00\u7ec4 Angular \u5305\u4ece 21.2.17 \u5347\u7ea7\u5230 21.2.19\uff0c\u4ee5\u4fee\u590d `@angular/compiler` \u548c `@angular/core` \u4e2d\u8bb0\u5f55\u7684 CVE-2026-69151\uff0c\u540c\u65f6\u4fdd\u6301 Angular \u8fd0\u884c\u65f6\u4e0e\u7f16\u8bd1\u5de5\u5177\u94fe\u7248\u672c\u4e00\u81f4\u3002\n\n| \u9879\u76ee | \u5185\u5bb9 |\n|---|---|\n| PR | [782419](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419) |\n| \u4f5c\u8005 | Dingmeng Xue |\n| \u72b6\u6001 | Active\uff08\u975e\u8349\u7a3f\uff0c\u5f53\u524d\u5408\u5e76\u72b6\u6001\u4e3a succeeded\uff09 |\n| \u5206\u652f | `dixue/angular-cve-69151` \u2192 `main` |\n| \u53d8\u66f4\u7edf\u8ba1 | 1 \u4e2a\u63d0\u4ea4\uff0c2 \u4e2a\u6587\u4ef6\uff0c\u65b0\u589e 182 \u884c\uff0c\u5220\u9664 70 \u884c |\n\n### \u76ee\u5f55\n\n- [\u95ee\u9898\u80cc\u666f](#\u95ee\u9898\u80cc\u666f)\n- [\u53d8\u66f4\u6982\u89c8](#\u53d8\u66f4\u6982\u89c8)\n- [\u6d4b\u8bd5\u7528\u4f8b\u89e3\u6790](#\u6d4b\u8bd5\u7528\u4f8b\u89e3\u6790)\n\n### \u95ee\u9898\u80cc\u666f\n\n**\u5df2\u786e\u8ba4\u7684\u610f\u56fe\uff1a** PR \u63cf\u8ff0\u548c\u56db\u4e2a\u5173\u8054 Bug \u5de5\u4f5c\u9879\u5171\u540c\u6307\u51fa\uff0c\u793a\u4f8b Angular \u5bbf\u4e3b\u5e94\u7528\u7684\u4f9d\u8d56\u6811\u5305\u542b CVE-2026-69151\u3002\u544a\u8b66\u5206\u522b\u8986\u76d6 `@angular/compiler` \u4e0e `@angular/core`\uff0c\u5e76\u8bb0\u5f55\u4e86\u4f9d\u8d56\u7248\u672c 21.2.7 \u548c 21.2.17\uff1b\u672c PR \u76f4\u63a5\u5904\u7406\u5f53\u524d\u6e05\u5355\u4e2d\u7684 21.2.17\uff0c\u5c06\u76f8\u5173 Angular \u5305\u66f4\u65b0\u5230 21.2.19\u3002PR \u7684\u76ee\u6807\u662f\u7528\u5df2\u4fee\u8865\u7248\u672c\u6d88\u9664\u8fd9\u4e9b\u4f9d\u8d56\u544a\u8b66\uff0c\u800c\u4e0d\u662f\u4fee\u6539\u5e94\u7528\u529f\u80fd\u3002\n\n**\u8865\u5145\u80cc\u666f\uff1a** \u5b89\u5168\u4f9d\u8d56\u66f4\u65b0\u9700\u8981\u53ca\u65f6\u63a8\u8fdb\uff0c\u540c\u65f6\u4ecd\u9700\u7531\u7ef4\u62a4\u8005\u786e\u8ba4\u8865\u4e01\u4e0e\u793a\u4f8b\u5e94\u7528\u7684\u6784\u5efa\u65b9\u5f0f\u517c\u5bb9\u3002\u4e3a\u51cf\u5c11\u6539\u52a8\u8303\u56f4\uff0c\u672c\u6b21\u91c7\u7528\u540c\u4e00 Angular \u6b21\u7248\u672c\u7ebf\u5185\u7684\u8865\u4e01\u5347\u7ea7\uff0c\u53ea\u8c03\u6574\u4f9d\u8d56\u58f0\u660e\u548c\u9501\u5b9a\u7ed3\u679c\u3002\n\n**\u4ece\u4ee3\u7801\u53d8\u66f4\u63a8\u65ad\uff1a** Angular \u5305\u4e4b\u95f4\u5b58\u5728\u4e25\u683c\u6216\u7d27\u5bc6\u7684 peer dependency \u7248\u672c\u5173\u7cfb\uff0c\u56e0\u6b64 PR \u6ca1\u6709\u53ea\u5347\u7ea7\u88ab\u544a\u8b66\u76f4\u63a5\u70b9\u540d\u7684 `compiler` \u548c `core`\uff0c\u800c\u662f\u540c\u6b65\u5347\u7ea7 `common`\u3001`forms`\u3001`platform-browser`\u3001`platform-browser-dynamic`\u3001`router` \u4ee5\u53ca\u7f16\u8bd1\u671f\u7684 `compiler-cli`\u3002\u8fd9\u4f7f\u8fd0\u884c\u65f6\u3001\u6d4f\u89c8\u5668\u96c6\u6210\u3001\u8def\u7531\u3001\u8868\u5355\u548c\u7f16\u8bd1\u5de5\u5177\u7ee7\u7eed\u4f7f\u7528\u540c\u4e00\u8865\u4e01\u7248\u672c\uff1b\u8be5\u4e00\u81f4\u6027\u52a8\u673a\u7531\u9501\u6587\u4ef6\u4e2d\u7684 peer dependency \u53d8\u5316\u652f\u6301\uff0c\u4f46 PR \u63cf\u8ff0\u6ca1\u6709\u9010\u9879\u8bf4\u660e\u3002\n\n## \u53d8\u66f4\u6982\u89c8\n\n### 1. Angular \u76f4\u63a5\u4f9d\u8d56\u7248\u672c\u5bf9\u9f50\n\n- **\u89e3\u51b3\u7684\u95ee\u9898\u90e8\u5206\uff1a** \u79fb\u9664\u5e94\u7528\u6e05\u5355\u4e2d\u5bf9 Angular 21.2.17 \u7684\u76f4\u63a5\u5f15\u7528\uff0c\u5e76\u5c06\u53d7\u5230 CVE \u544a\u8b66\u5f71\u54cd\u7684 `@angular/compiler`\u3001`@angular/core` \u66f4\u65b0\u5230 21.2.19\u3002\n- **\u6838\u5fc3\u7ec4\u4ef6/\u6587\u4ef6\uff1a** [`sample/angular-host-app/package.json`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/package.json&amp;_a=files)\u3002\n- **\u91c7\u7528\u8fd9\u79cd\u65b9\u5f0f\u7684\u539f\u56e0\uff1a** \u5df2\u786e\u8ba4\u7684\u4fee\u590d\u7b56\u7565\u662f\u7a84\u8303\u56f4\u8865\u4e01\u5347\u7ea7\u3002\u8be5\u6587\u4ef6\u628a\u4e03\u4e2a Angular \u8fd0\u884c\u65f6/\u6846\u67b6\u5305\u4ee5\u53ca\u5f00\u53d1\u4f9d\u8d56 `@angular/compiler-cli` \u7edf\u4e00\u4ece `^21.2.17` \u8c03\u6574\u4e3a `^21.2.19`\uff0c\u6ca1\u6709\u6539\u52a8\u5e94\u7528\u6e90\u7801\u3001\u811a\u672c\u6216\u5176\u4ed6\u9876\u5c42\u4f9d\u8d56\u3002\n- **\u8bf7\u6c42\u6216\u6570\u636e\u6d41\uff1a** \u8fd9\u4e2a\u6a21\u5757\u6ca1\u6709\u65b0\u589e\u8fd0\u884c\u65f6\u8bf7\u6c42\u5904\u7406\u94fe\u8def\u3002\u5b89\u88c5\u9636\u6bb5\uff0c\u5305\u7ba1\u7406\u5668\u8bfb\u53d6 `package.json` \u7684\u7248\u672c\u8303\u56f4\u5e76\u89e3\u6790 Angular 21.2.19\uff1b\u6784\u5efa\u9636\u6bb5\uff0c`compiler-cli` \u4e0e `compiler` \u53c2\u4e0e\u6a21\u677f\u548c TypeScript \u7f16\u8bd1\uff1b\u5e94\u7528\u8fd0\u884c\u65f6\u5219\u7531 `core`\u3001`common`\u3001\u8868\u5355\u3001\u8def\u7531\u548c\u6d4f\u89c8\u5668\u5e73\u53f0\u5305\u5171\u540c\u63d0\u4f9b\u73b0\u6709\u529f\u80fd\u3002\n\n### 2. \u53ef\u91cd\u590d\u5b89\u88c5\u7684\u4f9d\u8d56\u6811\u66f4\u65b0\n\n- **\u89e3\u51b3\u7684\u95ee\u9898\u90e8\u5206\uff1a** \u5c06\u6e05\u5355\u4e2d\u7684\u7248\u672c\u5347\u7ea7\u843d\u5b9e\u5230\u53ef\u91cd\u590d\u5b89\u88c5\u7684\u9501\u5b9a\u4f9d\u8d56\u6811\uff0c\u786e\u4fdd\u5b9e\u9645\u5b89\u88c5\u7684\u662f 21.2.19\uff0c\u800c\u4e0d\u53ea\u662f\u6269\u5927\u6216\u6539\u53d8\u7248\u672c\u58f0\u660e\u3002\n- **\u6838\u5fc3\u7ec4\u4ef6/\u6587\u4ef6\uff1a** [`sample/angular-host-app/package-lock.json`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/package-lock.json&amp;_a=files)\u3002\n- **\u91c7\u7528\u8fd9\u79cd\u65b9\u5f0f\u7684\u539f\u56e0\uff1a** `package-lock.json` \u8bb0\u5f55\u7cbe\u786e\u7248\u672c\u3001\u5305\u6e90\u3001\u5b8c\u6574\u6027\u6458\u8981\u3001\u4f9d\u8d56\u5173\u7cfb\u548c\u5e73\u53f0\u5143\u6570\u636e\u3002\u540c\u6b65\u63d0\u4ea4\u9501\u6587\u4ef6\u53ef\u4ee5\u8ba9 CI \u548c\u5f00\u53d1\u73af\u5883\u6309\u76f8\u540c\u89e3\u6790\u7ed3\u679c\u5b89\u88c5\u4f9d\u8d56\uff0c\u5e76\u4f7f Angular \u5305\u4e4b\u95f4\u7684 peer dependency \u6307\u5411 21.2.19\u3002\n- **\u8bf7\u6c42\u6216\u6570\u636e\u6d41\uff1a** `npm` \u5148\u8bfb\u53d6\u9876\u5c42\u6e05\u5355\uff0c\u518d\u6309\u9501\u6587\u4ef6\u53d6\u5f97\u7cbe\u786e\u5305\u7248\u672c\u3002\u89e3\u6790\u540e\u7684\u4f9d\u8d56\u56fe\u5c06 Angular \u7684 `common`\u3001`compiler`\u3001`core`\u3001`forms`\u3001\u6d4f\u89c8\u5668\u5e73\u53f0\u5305\u548c `router` \u56fa\u5b9a\u5230 21.2.19\uff1b`compiler-cli` \u540c\u6b65\u5230 21.2.19\uff0c\u5e76\u5e26\u5165\u5176\u89e3\u6790\u51fa\u7684 Babel \u5b50\u4f9d\u8d56\u66f4\u65b0\u3002\u9501\u6587\u4ef6\u8fd8\u8865\u5145\u4e86\u90e8\u5206\u53ef\u9009\u539f\u751f\u5305\u7684 `libc` \u5e73\u53f0\u6761\u4ef6\uff0c\u8fd9\u4e9b\u5185\u5bb9\u5c5e\u4e8e\u91cd\u65b0\u89e3\u6790\u4f9d\u8d56\u6811\u540e\u7684\u5b89\u88c5\u5143\u6570\u636e\u3002\n\n### 3. \u7f16\u8bd1\u5de5\u5177\u94fe\u7684\u4f20\u9012\u4f9d\u8d56\u5237\u65b0\n\n- **\u89e3\u51b3\u7684\u95ee\u9898\u90e8\u5206\uff1a** \u8ba9\u5347\u7ea7\u540e\u7684 Angular \u7f16\u8bd1\u5668 CLI \u4f7f\u7528\u4e0e\u5176 21.2.19 \u5305\u63cf\u8ff0\u4e00\u81f4\u7684\u4f20\u9012\u4f9d\u8d56\u3002\n- **\u6838\u5fc3\u7ec4\u4ef6/\u6587\u4ef6\uff1a** [`sample/angular-host-app/package-lock.json`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/package-lock.json&amp;_a=files) \u4e2d `@angular/compiler-cli` \u7684\u9501\u5b9a\u6761\u76ee\u53ca\u5176\u5d4c\u5957 Babel \u6761\u76ee\u3002\n- **\u91c7\u7528\u8fd9\u79cd\u65b9\u5f0f\u7684\u539f\u56e0\uff1a** \u8fd9\u662f\u9501\u6587\u4ef6\u6839\u636e\u65b0\u7248 `@angular/compiler-cli` \u4f9d\u8d56\u58f0\u660e\u751f\u6210\u7684\u7ed3\u679c\uff0c\u800c\u4e0d\u662f PR \u5355\u72ec\u58f0\u660e\u7684\u4e00\u9879\u529f\u80fd\u6539\u9020\u3002\u53ef\u89c1\u53d8\u5316\u5305\u62ec\u8be5\u5305\u4f7f\u7528\u7684 `@babel/core` \u4ece 7.29.0 \u66f4\u65b0\u5230 7.29.7\uff0c\u4ee5\u53ca\u76f8\u5e94 helper\u3001parser\u3001types \u548c generator \u6761\u76ee\u7684\u8c03\u6574\u3002\n- **\u8bf7\u6c42\u6216\u6570\u636e\u6d41\uff1a** \u5728\u6784\u5efa\u8fc7\u7a0b\u4e2d\uff0cAngular \u7f16\u8bd1\u5668 CLI \u8c03\u7528\u5176 Babel \u76f8\u5173\u4f20\u9012\u4f9d\u8d56\u5904\u7406\u548c\u751f\u6210\u4ee3\u7801\uff1b\u8fd0\u884c\u65f6\u5e94\u7528\u8bf7\u6c42\u4e0d\u4f1a\u76f4\u63a5\u7ecf\u8fc7\u8fd9\u4e9b\u5305\u3002\u8fd9\u91cc\u63cf\u8ff0\u7684\u662f\u6784\u5efa\u6570\u636e\u6d41\uff0c\u4f9d\u636e\u662f\u9501\u6587\u4ef6\u4e2d\u7684\u4f9d\u8d56\u5d4c\u5957\u5173\u7cfb\u3002\n\n## \u6d4b\u8bd5\u7528\u4f8b\u89e3\u6790\n\n\u672c PR **\u6ca1\u6709\u4fee\u6539\u6216\u65b0\u589e\u4efb\u4f55\u6d4b\u8bd5\u6587\u4ef6\uff0c\u56e0\u6b64\u6ca1\u6709\u53ef\u9010\u9879\u679a\u4e3e\u7684 changed test case**\u3002\n\nPR \u63cf\u8ff0\u63d0\u4f9b\u4e86\u4ee5\u4e0b\u9a8c\u8bc1\u8bb0\u5f55\uff0c\u4f46\u5b83\u4eec\u4e0d\u662f\u672c\u6b21\u53d8\u66f4\u4e2d\u7684\u6d4b\u8bd5\u7528\u4f8b\uff1a\n\n1. **\u4f9d\u8d56\u7248\u672c\u68c0\u67e5**\n   - **\u573a\u666f\uff1a** \u786e\u8ba4\u5b89\u88c5\u89e3\u6790\u7ed3\u679c\u5305\u542b\u76ee\u6807\u8865\u4e01\u7248\u672c\u3002\n   - **\u8f93\u5165/\u8bbe\u7f6e\uff1a** \u5728 `sample/angular-host-app` \u7684\u4f9d\u8d56\u73af\u5883\u4e2d\u8fd0\u884c `npm ls`\uff0c\u68c0\u67e5 `@angular/compiler`\u3001`@angular/core` \u548c `@angular/compiler-cli`\u3002\n   - **\u53ef\u89c2\u5bdf\u7684\u6210\u529f\u6761\u4ef6\uff1a** \u4e09\u4e2a\u5305\u5747\u89e3\u6790\u4e3a 21.2.19\u3002\n   - **\u8bf4\u660e\u7684\u884c\u4e3a\uff1a** \u9876\u5c42\u4f9d\u8d56\u58f0\u660e\u4e0e\u9501\u6587\u4ef6\u5171\u540c\u4f7f\u88ab\u544a\u8b66\u7684\u8fd0\u884c\u65f6\u5305\u53ca\u914d\u5957\u7f16\u8bd1 CLI \u843d\u5230\u76ee\u6807\u7248\u672c\u3002\n\n2. **\u5e94\u7528\u6784\u5efa\u9a8c\u8bc1**\n   - **\u573a\u666f\uff1a** \u786e\u8ba4\u5347\u7ea7\u540e\u7684 Angular \u4f9d\u8d56\u6811\u4ecd\u53ef\u7f16\u8bd1\u8be5\u793a\u4f8b\u5e94\u7528\u3002\n   - **\u8f93\u5165/\u8bbe\u7f6e\uff1a** \u8fd0\u884c\u73b0\u6709\u7684 `npm run build`\uff1bPR \u6570\u636e\u5305\u672a\u63d0\u4f9b\u989d\u5916 fixture\u3001mock \u6216\u65ad\u8a00\u7ec6\u8282\u3002\n   - **\u53ef\u89c2\u5bdf\u7684\u6210\u529f\u6761\u4ef6\uff1a** \u6784\u5efa\u547d\u4ee4\u6210\u529f\u5b8c\u6210\u3002\n   - **\u8bf4\u660e\u7684\u884c\u4e3a\uff1a** Angular 21.2.19 \u7684\u8fd0\u884c\u65f6\u5305\u3001\u7f16\u8bd1\u5668\u4e0e\u73b0\u6709\u5e94\u7528\u6e90\u7801\u80fd\u591f\u5b8c\u6210\u65e2\u6709\u6784\u5efa\u6d41\u7a0b\u3002\n\n3. **\u73b0\u6709\u6d4f\u89c8\u5668\u6d4b\u8bd5\u547d\u4ee4**\n   - **\u573a\u666f\uff1a** \u5c1d\u8bd5\u4ee5\u65e0\u76d1\u89c6\u3001Chrome Headless \u6a21\u5f0f\u8fd0\u884c\u73b0\u6709\u6d4b\u8bd5\u3002\n   - **\u8f93\u5165/\u8bbe\u7f6e\uff1a** `npm test -- --watch=false --browsers=ChromeHeadless`\u3002\n   - **\u53ef\u89c2\u5bdf\u7ed3\u679c\uff1a** \u8be5\u547d\u4ee4\u4ecd\u88ab\u5df2\u6709\u4ee3\u7801\u5bf9\u5df2\u79fb\u9664 Angular \u6d4b\u8bd5 API \u7684\u5bfc\u5165\u6240\u963b\u585e\uff0c\u672a\u5f62\u6210\u901a\u8fc7\u7ed3\u679c\u3002\n   - **\u8bf4\u660e\u7684\u884c\u4e3a\uff1a** \u53ef\u7528\u8bc1\u636e\u53ea\u8868\u660e\u8fd9\u662f\u5347\u7ea7\u524d\u5df2\u5b58\u5728\u7684\u6d4b\u8bd5\u542f\u52a8\u963b\u585e\uff1b\u6570\u636e\u5305\u6ca1\u6709\u63d0\u4f9b\u5177\u4f53\u53d7\u5f71\u54cd\u6d4b\u8bd5\u540d\u79f0\u3001fixture\u3001mock\u3001\u65ad\u8a00\u6216\u672c PR \u5bf9\u6d4b\u8bd5\u4ee3\u7801\u7684\u6539\u52a8\uff0c\u56e0\u6b64\u4e0d\u80fd\u636e\u6b64\u63a8\u65ad\u66f4\u591a\u6d4b\u8bd5\u8986\u76d6\u3002\n", "creation_timestamp": "2026-09-18T16:20:44.250594Z"}, {"uuid": "232438a9-6bd5-47a0-a491-687e7695c19d", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-69151", "type": "seen", "source": "https://gist.github.com/djlan/12f00d62cb0b23a8498e3941b9771770", "content": "# [SECURITY] \u5c06 Angular \u5347\u7ea7\u5230 21.2.19 \u5e76\u79fb\u9664\u5df2\u5f03\u7528\u7684\u6d4f\u89c8\u5668\u5f15\u5bfc\u65b9\u5f0f\n\n**\u4e00\u53e5\u8bdd\u603b\u7ed3\uff1a** \u6b64 PR \u5c06 Angular \u793a\u4f8b\u5bbf\u4e3b\u5e94\u7528\u7684\u6838\u5fc3\u6846\u67b6\u5305\u7edf\u4e00\u5347\u7ea7\u5230 21.2.19\uff0c\u4ee5\u4fee\u590d `@angular/compiler` \u548c `@angular/core` \u4e2d\u7684 CVE-2026-69151\uff0c\u5e76\u540c\u6b65\u8fc1\u79fb\u5e94\u7528\u542f\u52a8\u4e0e Karma \u6d4b\u8bd5\u5165\u53e3\uff0c\u4f7f\u5176\u4e0d\u518d\u4f9d\u8d56\u5df2\u5f03\u7528\u7684 `@angular/platform-browser-dynamic`\u3002\n\n| \u9879\u76ee | \u5185\u5bb9 |\n|---|---|\n| PR | [782419](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419) |\n| \u4f5c\u8005 | Dingmeng Xue |\n| \u72b6\u6001 | Active\uff0c\u975e\u8349\u7a3f\uff1b\u6570\u636e\u5305\u8bb0\u5f55\u7684\u5408\u5e76\u72b6\u6001\u4e3a `succeeded` |\n| \u5206\u652f | `dixue/angular-cve-69151` \u2192 `main` |\n| \u53d8\u66f4\u7edf\u8ba1 | 3 \u4e2a\u63d0\u4ea4\u30013 \u6b21\u8fed\u4ee3\uff1b\u6570\u636e\u5305\u6c47\u603b\u6807\u8bb0 7 \u4e2a\u6587\u4ef6\uff0c\u6240\u9644\u5b8c\u6574 diff \u5b9e\u9645\u8986\u76d6 8 \u4e2a\u8def\u5f84\uff08\u5305\u62ec\u5220\u9664 `src/test.ts`\uff09\uff1b\u6309 diff \u8ba1\u7b97\u7ea6\u65b0\u589e 179 \u884c\u3001\u5220\u9664 127 \u884c |\n\n## \u76ee\u5f55\n\n- [\u53d8\u66f4\u6982\u89c8](#\u53d8\u66f4\u6982\u89c8)\n  - [Angular \u5b89\u5168\u7248\u672c\u5347\u7ea7\u4e0e\u4f9d\u8d56\u6536\u655b](#angular-\u5b89\u5168\u7248\u672c\u5347\u7ea7\u4e0e\u4f9d\u8d56\u6536\u655b)\n  - [\u5e94\u7528\u6d4f\u89c8\u5668\u542f\u52a8\u65b9\u5f0f\u8fc1\u79fb](#\u5e94\u7528\u6d4f\u89c8\u5668\u542f\u52a8\u65b9\u5f0f\u8fc1\u79fb)\n  - [Karma \u6d4b\u8bd5\u53d1\u73b0\u4e0e Angular \u6d4b\u8bd5 API \u8fc1\u79fb](#karma-\u6d4b\u8bd5\u53d1\u73b0\u4e0e-angular-\u6d4b\u8bd5-api-\u8fc1\u79fb)\n  - [TypeScript \u6a21\u5757\u89e3\u6790\u914d\u7f6e\u66f4\u65b0](#typescript-\u6a21\u5757\u89e3\u6790\u914d\u7f6e\u66f4\u65b0)\n- [\u6d4b\u8bd5\u7528\u4f8b\u89e3\u6790](#\u6d4b\u8bd5\u7528\u4f8b\u89e3\u6790)\n\n**\u5df2\u786e\u8ba4\u7684\u610f\u56fe\uff1a** \u7ec4\u4ef6\u6cbb\u7406\u5de5\u4f5c\u9879\u5206\u522b\u62a5\u544a\u4e86 `@angular/compiler` \u548c `@angular/core` \u4e2d\u7684\u9ad8\u4e25\u91cd\u6027 CVE-2026-69151\uff0c\u6d89\u53ca\u5e94\u7528\u4f9d\u8d56\u6811\u4e2d\u51fa\u73b0\u7684 21.2.7 \u548c 21.2.17 \u7248\u672c\u3002PR \u7684\u76f4\u63a5\u76ee\u6807\u662f\u628a\u76f8\u5173 Angular \u5305\u7edf\u4e00\u5347\u7ea7\u5230\u5df2\u4fee\u590d\u7684 21.2.19\uff0c\u5e76\u901a\u8fc7\u53d7\u652f\u6301\u7684\u4f9d\u8d56\u5347\u7ea7\u8def\u5f84\u6d88\u9664\u8fd9\u4e9b\u544a\u8b66\u3002\u7531\u4e8e Angular \u5305\u4e4b\u95f4\u5b58\u5728\u4e25\u683c\u7684\u5bf9\u7b49\u7248\u672c\u5173\u7cfb\uff0c\u4fee\u590d\u4e0d\u80fd\u53ea\u66ff\u6362\u5355\u4e2a\u53d7\u5f71\u54cd\u5305\uff0c\u800c\u9700\u8981\u8ba9 common\u3001compiler\u3001core\u3001forms\u3001platform-browser\u3001router \u548c compiler-cli \u4fdd\u6301\u4e00\u81f4\u7248\u672c\u3002\n\n**\u5df2\u786e\u8ba4\u7684\u610f\u56fe\uff1a** \u5347\u7ea7\u8fd8\u9700\u8981\u79fb\u9664\u5df2\u5f03\u7528\u7684 `@angular/platform-browser-dynamic`\u3002\u5e94\u7528\u5fc5\u987b\u5728\u4e0d\u6539\u53d8\u73b0\u6709 `AppModule` \u542f\u52a8\u76ee\u6807\u7684\u524d\u63d0\u4e0b\u6539\u7528 `@angular/platform-browser` \u63d0\u4f9b\u7684\u5165\u53e3\uff1b\u6d4b\u8bd5\u4fa7\u4e5f\u5fc5\u987b\u505c\u6b62\u901a\u8fc7\u65e7\u7684 browser-dynamic \u6d4b\u8bd5\u5e73\u53f0\u548c\u624b\u5199 Webpack `require.context` \u6765\u521d\u59cb\u5316\u3001\u641c\u7d22\u5e76\u52a0\u8f7d spec\u3002\n\n**\u7531\u4ee3\u7801\u5dee\u5f02\u63a8\u65ad\uff1a** \u4e3a\u8ba9\u5347\u7ea7\u540e\u7684 Angular \u6784\u5efa\u94fe\u76f4\u63a5\u5904\u7406\u5e94\u7528\u548c\u6d4b\u8bd5\u6a21\u5757\uff0cPR \u540c\u65f6\u91c7\u7528 Karma \u539f\u751f spec \u53d1\u73b0\u4ee5\u53ca TypeScript \u7684 `bundler` \u6a21\u5757\u89e3\u6790\u6a21\u5f0f\u3002\u8fd9\u4e9b\u8c03\u6574\u670d\u52a1\u4e8e\u65b0\u7248\u5de5\u5177\u94fe\u517c\u5bb9\u6027\uff1b\u6570\u636e\u5305\u6ca1\u6709\u63d0\u4f9b\u66f4\u7ec6\u7684\u8bbe\u8ba1\u6587\u6863\uff0c\u56e0\u6b64\u4e0d\u80fd\u8fdb\u4e00\u6b65\u65ad\u8a00\u5b83\u4eec\u89e3\u51b3\u4e86\u54ea\u4e9b\u7279\u5b9a\u7f16\u8bd1\u9519\u8bef\u3002\n\n## \u53d8\u66f4\u6982\u89c8\n\n### Angular \u5b89\u5168\u7248\u672c\u5347\u7ea7\u4e0e\u4f9d\u8d56\u6536\u655b\n\n**\u89e3\u51b3\u7684\u95ee\u9898\uff1a** \u4fee\u590d\u5de5\u4f5c\u9879\u4e2d\u660e\u786e\u8bb0\u5f55\u7684 `@angular/compiler` \u4e0e `@angular/core` \u9ad8\u4e25\u91cd\u6027\u6f0f\u6d1e\uff0c\u540c\u65f6\u907f\u514d Angular \u6846\u67b6\u5305\u7248\u672c\u4e0d\u4e00\u81f4\u9020\u6210\u5bf9\u7b49\u4f9d\u8d56\u51b2\u7a81\u3002\n\n**\u6838\u5fc3\u7ec4\u4ef6\u4e0e\u6587\u4ef6\uff1a**\n\n- [`sample/angular-host-app/package.json`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/package.json&amp;_a=files)\uff1a\u5c06 `@angular/common`\u3001`compiler`\u3001`core`\u3001`forms`\u3001`platform-browser`\u3001`router` \u548c `compiler-cli` \u4ece 21.2.17 \u5347\u7ea7\u5230 21.2.19\uff0c\u5e76\u5220\u9664 `@angular/platform-browser-dynamic` \u7684\u76f4\u63a5\u4f9d\u8d56\u3002\n- [`sample/angular-host-app/package-lock.json`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/package-lock.json&amp;_a=files)\uff1a\u9501\u5b9a\u4e0a\u8ff0 21.2.19 \u5305\u53ca\u5176\u89e3\u6790\u540e\u7684\u4f20\u9012\u4f9d\u8d56\uff0c\u79fb\u9664 browser-dynamic \u5305\u8bb0\u5f55\uff1b\u540c\u65f6\u4fdd\u7559\u5df2\u5408\u5165\u7684 `@azure-notebooks/core-contract` 1.7.11\u3002\n\n**\u4e3a\u4ec0\u4e48\u91c7\u7528\u8fd9\u79cd\u65b9\u5f0f\uff1a** \u5df2\u786e\u8ba4\u7684\u65b9\u6848\u662f\u5347\u7ea7\u5230\u6846\u67b6\u5b98\u65b9\u4fee\u590d\u7248\u672c\uff0c\u800c\u4e0d\u662f\u5728\u5e94\u7528\u4ee3\u7801\u4e2d\u589e\u52a0\u672c\u5730\u89c4\u907f\u903b\u8f91\u3002\u76f8\u5173 Angular \u5305\u88ab\u6210\u7ec4\u5347\u7ea7\uff0c\u662f\u56e0\u4e3a\u9501\u6587\u4ef6\u663e\u793a\u5b83\u4eec\u901a\u8fc7\u7cbe\u786e\u7684 peer dependency \u76f8\u4e92\u7ea6\u675f\uff1b\u7edf\u4e00\u5230 21.2.19 \u80fd\u4f7f\u7f16\u8bd1\u5668\u3001\u8fd0\u884c\u65f6\u3001\u8868\u5355\u3001\u8def\u7531\u548c\u6d4f\u89c8\u5668\u5e73\u53f0\u4f7f\u7528\u540c\u4e00\u8865\u4e01\u7ea7\u522b\u3002\n\n**\u8bf7\u6c42\u4e0e\u6570\u636e\u6d41\uff1a** \u5305\u7ba1\u7406\u5668\u8bfb\u53d6 `package.json` \u7684\u7248\u672c\u8303\u56f4\uff0c\u518d\u6309\u7167 `package-lock.json` \u5b89\u88c5\u786e\u5b9a\u7684 21.2.19 \u4f9d\u8d56\u6811\u3002\u6784\u5efa\u65f6\uff0cAngular \u7f16\u8bd1\u5668\u4e0e compiler-cli \u5904\u7406\u5e94\u7528\u6a21\u5757\uff1b\u8fd0\u884c\u65f6\uff0ccore\u3001common\u3001forms\u3001router \u548c platform-browser \u5171\u540c\u63d0\u4f9b\u5e94\u7528\u6240\u9700\u7684\u6846\u67b6\u80fd\u529b\u3002\u6f0f\u6d1e\u4fee\u590d\u7531\u5b89\u88c5\u5e76\u6267\u884c\u5df2\u4fee\u590d\u7248\u672c\u5b9e\u73b0\uff0c\u800c\u4e0d\u662f\u7531\u989d\u5916\u7684\u8fd0\u884c\u65f6\u5206\u652f\u5904\u7406\u3002\n\n### \u5e94\u7528\u6d4f\u89c8\u5668\u542f\u52a8\u65b9\u5f0f\u8fc1\u79fb\n\n**\u89e3\u51b3\u7684\u95ee\u9898\uff1a** \u5728\u5220\u9664 `@angular/platform-browser-dynamic` \u540e\uff0c\u5e94\u7528\u5165\u53e3\u4ecd\u9700\u521b\u5efa\u6d4f\u89c8\u5668\u5e73\u53f0\u5e76\u5f15\u5bfc\u73b0\u6709 `AppModule`\u3002\n\n**\u6838\u5fc3\u7ec4\u4ef6\u4e0e\u6587\u4ef6\uff1a**\n\n- [`sample/angular-host-app/src/main.ts`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/src/main.ts&amp;_a=files)\uff1a\u628a `platformBrowserDynamic` \u66ff\u6362\u4e3a `@angular/platform-browser` \u4e2d\u7684 `platformBrowser`\uff0c\u968f\u540e\u4ecd\u8c03\u7528 `bootstrapModule(AppModule)`\u3002\n\n**\u4e3a\u4ec0\u4e48\u91c7\u7528\u8fd9\u79cd\u65b9\u5f0f\uff1a** PR \u63cf\u8ff0\u660e\u786e\u8981\u6c42\u66ff\u6362\u5df2\u5f03\u7528\u7684 browser-dynamic \u5f15\u5bfc\u673a\u5236\u3002\u65b0\u5b9e\u73b0\u6cbf\u7528\u6a21\u5757\u5f0f\u542f\u52a8\u7ed3\u6784\uff0c\u53ea\u66ff\u6362\u5e73\u53f0\u521b\u5efa API\uff0c\u56e0\u6b64\u65e0\u9700\u91cd\u5199 `AppModule` \u6216\u5e94\u7528\u521d\u59cb\u5316\u903b\u8f91\u3002\n\n**\u8bf7\u6c42\u4e0e\u6570\u636e\u6d41\uff1a** \u6d4f\u89c8\u5668\u52a0\u8f7d\u5165\u53e3\u6587\u4ef6\u540e\uff0c\u4ee3\u7801\u4ecd\u5148\u6839\u636e\u73af\u5883\u51b3\u5b9a\u662f\u5426\u542f\u7528\u751f\u4ea7\u6a21\u5f0f\uff1b\u968f\u540e `platformBrowser()` \u521b\u5efa\u6d4f\u89c8\u5668\u5e73\u53f0\uff0c`bootstrapModule(AppModule)` \u542f\u52a8\u6839\u6a21\u5757\u3002\u542f\u52a8 Promise \u7684\u5f02\u5e38\u7ee7\u7eed\u6d41\u5411\u65e2\u6709\u7684 `console.error` \u5904\u7406\uff0c\u56e0\u6b64\u5165\u53e3\u7684\u63a7\u5236\u6d41\u4fdd\u6301\u4e0d\u53d8\uff0c\u53d8\u5316\u96c6\u4e2d\u5728\u5e73\u53f0\u63d0\u4f9b\u8005\u3002\n\n### Karma \u6d4b\u8bd5\u53d1\u73b0\u4e0e Angular \u6d4b\u8bd5 API \u8fc1\u79fb\n\n**\u89e3\u51b3\u7684\u95ee\u9898\uff1a** \u65e7\u6d4b\u8bd5\u5165\u53e3\u76f4\u63a5\u5bfc\u5165 `@angular/platform-browser-dynamic/testing`\uff0c\u5e76\u4f9d\u9760 `require.context` \u624b\u5de5\u9012\u5f52\u52a0\u8f7d\u6240\u6709 spec\uff1b\u5220\u9664 browser-dynamic \u4f9d\u8d56\u540e\uff0c\u8fd9\u6761\u8def\u5f84\u4e0d\u80fd\u7ee7\u7eed\u4f7f\u7528\u3002\u540c\u65f6\uff0c\u6d4b\u8bd5\u4ee3\u7801\u4f7f\u7528\u7684 `async` \u6d4b\u8bd5\u8f85\u52a9\u51fd\u6570\u88ab\u66ff\u6362\u4e3a\u5f53\u524d API \u540d\u79f0\u3002\n\n**\u6838\u5fc3\u7ec4\u4ef6\u4e0e\u6587\u4ef6\uff1a**\n\n- [`sample/angular-host-app/angular.json`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/angular.json&amp;_a=files)\uff1a\u4ece Karma builder \u914d\u7f6e\u4e2d\u5220\u9664\u663e\u5f0f\u7684 `main: \"src/test.ts\"`\u3002\n- [`sample/angular-host-app/src/test.ts`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/src/test.ts&amp;_a=files)\uff1a\u5220\u9664\u65e7\u6d4b\u8bd5\u5f15\u5bfc\u6587\u4ef6\uff0c\u5305\u62ec zone \u6d4b\u8bd5\u521d\u59cb\u5316\u3001BrowserDynamicTestingModule \u521d\u59cb\u5316\u548c `require.context` spec \u626b\u63cf\u3002\n- [`sample/angular-host-app/tsconfig.spec.json`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/tsconfig.spec.json&amp;_a=files)\uff1a\u4ece\u6d4b\u8bd5\u7f16\u8bd1\u5165\u53e3\u6587\u4ef6\u5217\u8868\u4e2d\u79fb\u9664 `src/test.ts`\uff0c\u7ee7\u7eed\u5305\u542b `src/**/*.spec.ts` \u548c\u58f0\u660e\u6587\u4ef6\u3002\n- [`sample/angular-host-app/src/app/notebook/notebook.component.spec.ts`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/src/app/notebook/notebook.component.spec.ts&amp;_a=files)\uff1a\u5c06 `async` \u5bfc\u5165\u4e0e `beforeEach(async(...))` \u6539\u4e3a `waitForAsync`\u3002\n\n**\u4e3a\u4ec0\u4e48\u91c7\u7528\u8fd9\u79cd\u65b9\u5f0f\uff1a** PR \u63cf\u8ff0\u660e\u786e\u6307\u51fa\u8fc1\u79fb\u5230 Karma \u539f\u751f spec discovery\u3002\u5220\u9664\u81ea\u5b9a\u4e49\u5165\u53e3\u540e\uff0c\u6d4b\u8bd5 builder \u53ef\u4f9d\u636e `tsconfig.spec.json` \u7684 `include` \u76f4\u63a5\u53d1\u73b0 spec\uff0c\u907f\u514d\u4e3a\u4e86\u6d4b\u8bd5\u521d\u59cb\u5316\u7ee7\u7eed\u4fdd\u7559\u5df2\u5f03\u7528\u5305\u3002`waitForAsync` \u5219\u4fdd\u6301\u539f\u6709\u5f02\u6b65 `beforeEach` \u7684\u7b49\u5f85\u8bed\u4e49\uff0c\u540c\u65f6\u4f7f\u7528\u65b0\u7248 Angular \u6d4b\u8bd5 API\u3002\n\n**\u8bf7\u6c42\u4e0e\u6570\u636e\u6d41\uff1a** \u6267\u884c Karma \u6d4b\u8bd5\u65f6\uff0cAngular builder \u4e0d\u518d\u5148\u8fd0\u884c `src/test.ts`\uff1b\u5b83\u6839\u636e\u6d4b\u8bd5 TypeScript \u914d\u7f6e\u6536\u96c6 `src/**/*.spec.ts`\uff0c\u7f16\u8bd1\u5e76\u4ea4\u7ed9 Karma/Jasmine \u6267\u884c\u3002\u8fdb\u5165 NotebookComponent spec \u540e\uff0c`waitForAsync` \u5305\u88c5\u7684\u5171\u4eab `beforeEach` \u914d\u7f6e `TestBed`\uff0cAngular \u6d4b\u8bd5\u73af\u5883\u7b49\u5f85\u5f02\u6b65\u521d\u59cb\u5316\u5b8c\u6210\u540e\u518d\u8fdb\u5165\u540e\u7eed\u6d4b\u8bd5\u9636\u6bb5\u3002\n\n### TypeScript \u6a21\u5757\u89e3\u6790\u914d\u7f6e\u66f4\u65b0\n\n**\u89e3\u51b3\u7684\u95ee\u9898\uff1a** \u8ba9 TypeScript \u7684\u6a21\u5757\u89e3\u6790\u65b9\u5f0f\u4e0e\u5f53\u524d Angular \u6253\u5305\u5de5\u5177\u94fe\u4fdd\u6301\u4e00\u81f4\u3002\n\n**\u6838\u5fc3\u7ec4\u4ef6\u4e0e\u6587\u4ef6\uff1a**\n\n- [`sample/angular-host-app/tsconfig.json`](https://dev.azure.com/devdiv/OnlineServices/_git/AzureNotebooks/pullrequest/782419?path=/sample/angular-host-app/tsconfig.json&amp;_a=files)\uff1a\u5c06 `moduleResolution` \u4ece `node` \u6539\u4e3a `bundler`\u3002\n\n**\u4e3a\u4ec0\u4e48\u91c7\u7528\u8fd9\u79cd\u65b9\u5f0f\uff1a** \u8fd9\u662f\u4ece\u4ee3\u7801\u5dee\u5f02\u5f97\u51fa\u7684\u517c\u5bb9\u6027\u63a8\u65ad\u3002`bundler` \u6a21\u5f0f\u8ba9 TypeScript \u6309\u9762\u5411\u6253\u5305\u5668\u7684\u89c4\u5219\u89e3\u6790\u5305\u5bfc\u51fa\uff0c\u4e0e Angular builder \u8d1f\u8d23\u6700\u7ec8\u6253\u5305\u7684\u7ed3\u6784\u76f8\u5339\u914d\uff1b\u6570\u636e\u5305\u6ca1\u6709\u8bb0\u5f55\u66f4\u5177\u4f53\u7684\u9009\u62e9\u4f9d\u636e\u3002\n\n**\u8bf7\u6c42\u4e0e\u6570\u636e\u6d41\uff1a** \u65e0\u8bba\u5e94\u7528\u6784\u5efa\u8fd8\u662f\u6d4b\u8bd5\u7f16\u8bd1\uff0cTypeScript \u90fd\u5148\u4f9d\u636e\u6839 `tsconfig.json` \u89e3\u6790 import\uff0c\u518d\u628a\u89e3\u6790\u540e\u7684\u6a21\u5757\u4ea4\u7ed9 Angular \u6784\u5efa\u94fe\u3002\u6b64 PR \u53ea\u6539\u53d8\u6a21\u5757\u67e5\u627e\u89c4\u5219\uff0c\u4e0d\u6539\u53d8\u4e1a\u52a1\u6570\u636e\u6216\u7528\u6237\u8bf7\u6c42\u5728\u5e94\u7528\u4e2d\u7684\u6d41\u8f6c\u3002\n\n## \u6d4b\u8bd5\u7528\u4f8b\u89e3\u6790\n\n\u6b64 PR **\u6ca1\u6709\u65b0\u589e\u3001\u5220\u9664\u6216\u6539\u5199\u4efb\u4f55\u53ef\u8bc6\u522b\u7684\u5177\u4f53 `it(...)` \u6d4b\u8bd5\u7528\u4f8b**\u3002\u6570\u636e\u5305\u4e2d\u7684\u552f\u4e00\u6d4b\u8bd5\u6e90\u7801\u53d8\u66f4\u4f4d\u4e8e NotebookComponent spec \u7684\u5171\u4eab\u521d\u59cb\u5316\u4ee3\u7801\uff1b\u6240\u9644 diff \u6ca1\u6709\u5c55\u793a\u5404\u4e2a\u6d4b\u8bd5\u7528\u4f8b\u7684\u540d\u79f0\u3001\u8f93\u5165\u6216\u65ad\u8a00\uff0c\u56e0\u6b64\u4e0d\u80fd\u636e\u6b64\u865a\u6784\u9010\u9879\u65ad\u8a00\u8bf4\u660e\u3002\n\n1. **NotebookComponent \u5171\u4eab\u5f02\u6b65\u521d\u59cb\u5316**\n   - **\u573a\u666f\uff1a** \u5728 NotebookComponent \u6d4b\u8bd5\u7ec4\u8fd0\u884c\u5177\u4f53\u7528\u4f8b\u4e4b\u524d\uff0c\u5b8c\u6210 Angular `TestBed` \u7684\u5f02\u6b65\u914d\u7f6e\u3002\n   - **\u8f93\u5165\u3001\u8bbe\u7f6e\u4e0e\u5939\u5177\uff1a** \u6d4b\u8bd5\u7ec4\u58f0\u660e `NotebookComponent` \u7c7b\u578b\u7684\u7ec4\u4ef6\u53d8\u91cf\u548c `ComponentFixture` \u5939\u5177\uff1b\u5171\u4eab `beforeEach` \u4f7f\u7528 `TestBed.configureTestingModule`\uff0c\u5e76\u628a `NotebookComponent` \u653e\u5165 `declarations`\u3002\u672c\u6b21\u53d8\u66f4\u4ec5\u628a\u5305\u88c5\u51fd\u6570\u4ece `async` \u66ff\u6362\u4e3a `waitForAsync`\u3002\n   - **Mock \u4e0e\u65ad\u8a00\uff1a** \u53ef\u7528 diff \u672a\u663e\u793a mock\uff0c\u4e5f\u6ca1\u6709\u4fee\u6539\u6216\u5c55\u793a\u5177\u4f53\u65ad\u8a00\uff1b\u4e0d\u80fd\u786e\u8ba4\u6d4b\u8bd5\u7ec4\u4e2d\u7684\u540e\u7eed\u7528\u4f8b\u5982\u4f55\u64cd\u4f5c fixture \u6216\u68c0\u67e5\u7ec4\u4ef6\u3002\n   - **\u53ef\u89c2\u5bdf\u7684\u6210\u529f\u6761\u4ef6\uff1a** `waitForAsync` \u80fd\u7b49\u5f85\u8be5\u521d\u59cb\u5316\u9636\u6bb5\u7684\u5f02\u6b65\u4efb\u52a1\u5b8c\u6210\uff0c\u4f7f Jasmine \u5728\u521d\u59cb\u5316\u7ed3\u675f\u540e\u7ee7\u7eed\u6267\u884c\u540e\u7eed hook \u548c\u6d4b\u8bd5\u3002PR \u63cf\u8ff0\u8bb0\u5f55 Karma \u80fd\u7f16\u8bd1\u5e76\u6267\u884c\u4e09\u4efd spec\uff0c\u4f46\u4ecd\u5b58\u5728 `app-notebook` \u672a\u58f0\u660e\u548c\u7f3a\u5c11\u5168\u5c40 `AzureNotebooks` \u7684\u65e2\u6709\u5939\u5177/\u5168\u5c40\u8bbe\u7f6e\u5931\u8d25\u3002\n   - **\u8be5\u53d8\u66f4\u8bf4\u660e\u7684\u884c\u4e3a\uff1a** \u65b0\u7248 Angular \u6d4b\u8bd5 API \u4ecd\u9700\u4fdd\u7559\u539f\u5148\u201c\u5148\u5b8c\u6210\u5f02\u6b65 TestBed \u521d\u59cb\u5316\uff0c\u518d\u8fd0\u884c\u7528\u4f8b\u201d\u7684\u6267\u884c\u987a\u5e8f\uff1b\u6b64\u6b21\u6d4b\u8bd5\u6e90\u7801\u4fee\u6539\u9a8c\u8bc1\u7684\u662f\u6d4b\u8bd5\u57fa\u7840\u8bbe\u65bd\u8fc1\u79fb\uff0c\u800c\u4e0d\u662f\u589e\u52a0\u65b0\u7684\u4e1a\u52a1\u884c\u4e3a\u8986\u76d6\u3002\n", "creation_timestamp": "2026-09-20T16:56:34.441376Z"}]}