Make runtime URL sanitizer selection namespace-aware so SVG and MathML host bindings match the security schema.
Cover SVG href/xlink:href and MathML href host binding cases, including dynamic hostElement resolution.
PR Close#69558
Host binding sanitization previously used the declaring directive or component selector to choose a compile-time security context. The same host binding can execute on a different concrete element through hostDirectives, inherited host bindings, dynamic directives, or createComponent hostElement usage.
Compute host binding security contexts against possible concrete hosts and defer URL versus ResourceURL selection to runtime when necessary. Resolve dynamic root host TNodes to their native tag before sanitizer and security-sensitive attribute checks.
Fixes angular#69550
PR Close#69558
Currently, the SVG sanitizer checks a static set of candidate attribute
names (`attributeName` and `attributename`). This approach misses other case
variations (such as `attributenAme` or others), which could potentially
bypass sanitization when binding sensitive attributes like `href` on
`<set>` or `<animate>` elements.
This change retrieves all attribute names of the SVG element, performs a
case-insensitive comparison with `'attributename'`, and sanitizes the value
if a match is found.
(cherry picked from commit 3499a1321b)
If a directive has an input declared as `dismissible = input<boolean>(true, {transform: booleanAttribute});` then the following templates were not compiling:
```
<div directiveName dismissible="true"></div>
<div directiveName dismissible></div>
```
This commit fixes the issue, without breaking contravariant consumers.
(cherry picked from commit 0ae6d81ed2)
Move the DebugSignalGraph, DebugSignalGraphEdge, and DebugSignalGraphNode interfaces from packages/core/src/render3/util/signal_debug.ts into the packages/core/primitives/devtools/src package. This decouples the signal graph debug types from runtime render3 utilities and allows devtools and internal core tooling to import them directly from primitives as type-only exports.
(cherry picked from commit d997a96b47)
This reverts commit 9b9b0e93c9.
This broke g3. Not sure yet why it didn't break externally. We can
investigate and fix following this revert.
(cherry picked from commit 1fb4678207)
This is a follow-up to #67997, which allowed explicit read generics with input transforms, such as `input<boolean>(false, {transform: booleanAttribute})`.
That fixed the declaration, but static template attributes like `dismissible="true"` and bare `dismissible` were still checked as strings against the read type. Allow the fallback write type to include static attribute strings so these template forms compile.
(cherry picked from commit 9b9b0e93c9)
Extract the AI tool definition interfaces from the core debug module to the devtools primitives module. This relocates ToolDefinition, ToolGroup, and DevtoolsToolDiscoveryEvent to the primitives folder, exposing them cleanly via "export type" in the devtools entry point, improving module organization and readability.
(cherry picked from commit bf6dba878e)
The previous fix for GHSA-692r-grfm-v8x7 was incomplete because it rejected script tags only when locating an explicit host element. Dynamic component instantiation can also infer the host element from the component selector.
Move the script-host rejection to the point where ComponentFactory has resolved the host element for either path, so createComponent rejects script hosts consistently.
(cherry picked from commit d7f70616a0)
When partial declarations are not preprocessed to AOT by the linker, the `ngDeclareComponent`
call causes them to be compiled ad-hoc. In this mode, NgModule imports in standalone components
would be dropped, deviating from the linker. This commit changes the ad-hoc compilation of
component declarations to pass the NgModule imports along just like the linker does.
Fixes#69451
(cherry picked from commit ecd047578e)
Fixes a minor issue where the `preload` function in `injectAsync` might cause an uncaught promise error.
I also fixed that in `onIdle` we were passing the wrong function into `assertInInjectionContext`.
(cherry picked from commit 91d168e74b)
Add handling in navigation for creating and destroying injectors scoped
to `ActivatedRoute` life.
The code for creating the injectors is certainly more complicated
than it _could_ be since there's no actual feature built around this yet.
Keeps as much implementation code tree-shakeable as possible:
Raw size: +764 bytes
Gzipped size: +182 bytes
(cherry picked from commit 1e79dd3140)
This commit addresses a scaling issue in the signal dependency graph where
the detection of duplicate dependency links would perform a linear scan across
all consumer links of all producers. The linear scan is replaced with a version
comparison of the dependency edge against the current epoch; if they are
equal the existing dependency edge is known to be valid in this epoch. This means
that the link won't be eligible for removal and therefore doesn't have to be
recreated.
(cherry picked from commit 327744ac17)
`COMMENT_DISALLOWED` is matched globally, so overlapping delimiter
sequences are skipped: `<!-->` only escapes the leading `<!--` and
leaves a live `-->` that can close a programmatically created comment
node early. Drop the `^` anchors so a standalone `>`/`->` is escaped
wherever it appears, which neutralizes the trailing delimiter left
behind by an earlier match.
(cherry picked from commit ea1a3ed64c)
Mark the iframe `credentialless` attribute as security-sensitive so dynamic
bindings are handled consistently with other iframe attributes that affect the
initial navigation, such as `sandbox`, `allow`, `referrerPolicy`, `csp`, and
`fetchPriority`.
Because `credentialless` must be present before the iframe starts loading to
affect the navigation’s credential mode, late dynamic updates can leave the final
DOM looking correct while the initial request was not loaded credentiallessly.
(cherry picked from commit 0152e3cbdf)
Fixes that when a listener unsubscribes from an `output` within its own callback, it was preventing subsequent listeners from running.
These changes fix the issue by not mutating the array while the emit loop is running, but replacing the listener with `null` and coming back later to remove it.
Fixes#69325.
(cherry picked from commit 28cb15a2bb)
Only cache locale data loaded from the global locale registry when an actual locale entry is found.
This prevents attacker-controlled missing locale identifiers from being retained indefinitely in SSR when locale lookup falls back to a parent locale or the built-in English locale, avoiding unbounded process memory growth in locale-aware pipes and formatters.
(cherry picked from commit 98f42eaaae)
Previously, the compiler disallowed translation of any attribute starting with 'on' for security reasons. This incorrectly disallowed translation of the 'on' attribute itself, which is not an event handler.
This commit introduces `isPossibleEventHandler` to verify that the property name has a length greater than 2 in addition to starting with 'on'. This allows attributes like 'on' to be translated while still correctly disallowing actual event handlers like 'onerror', 'onclick', etc.
(cherry picked from commit 417a4071a7)
`animate.leave` was skipped — the element was removed from the DOM
synchronously instead of running its leave animation — whenever a
sibling instance of the same template entered in a different DOM parent
during the same change-detection tick (e.g. an exclusive-expansion
accordion or nav where opening section B collapses section A).
`leavingNodes` is keyed by `TNode`, which is shared by every instance of
a template. When a node was inserted, `cancelLeavingNodes` force-removed
any tracked leaving node whose DOM parent differed from the entering
node's parent (the `leavingParent !== newParent` branch added to
de-duplicate a dynamic component re-rendered into a fresh overlay pane).
For two distinct live sibling instances that merely share a `TNode`,
"different parent" is the normal situation, so the still-animating
sibling was ripped out.
Track the declaration view of each leaving element alongside it, and
only perform the cross-parent removal when the entering element belongs
to the same declaration view as the leaving one — i.e. the same logical
view re-rendered, the case the branch was written for. Two distinct
instances of a shared template have different declaration views, so
their `animate.leave` is now left to run to completion.
This preserves the dynamic-component/overlay de-duplication (#67032) and
the drag-and-drop node-move rescue (#67361), which are unchanged.
Fixes#69291
(cherry picked from commit 6b5616b2c7)
Do not store HTTP transfer cache entries when either the request or response
uses `Cache-Control: no-store`, `Cache-Control: private`, or
`Cache-Control: no-cache`.
Also skip transfer cache when requests use the Fetch API `cache` option with
`no-store` or `no-cache`.
Because transfer cache serializes SSR HTTP responses into the rendered HTML,
Angular now treats these directives conservatively to avoid exposing sensitive
or explicitly uncacheable data through `TransferState`.
PR Close#69316
This test flakes occasionally because it is called in production when a platform is created and unregistered when a platform is destroyed. However, not all tests properly clean up their platforms, meaning we can accidentally leak platforms between tests. If this happens, we end up have an event listener created from the production code path and a second event listener from the test. When the test emits the event, both listeners respond and it causes too many responses which fails the test.
Ideally, all tests would clean up the platforms correctly, but this seems difficult to guarantee for all Angular tests and is likely to break over time. The simplest solution is just destroy any leaked platform before the test starts. It's a bit elegant, but the safest option.
(cherry picked from commit 492e3a2a1f)
Normalize SVG animation attributeName lookup to also recognize lowercase attributename before allowing dynamic animation value bindings.
Add runtime and platform-server SSR regression coverage for lowercase attributename retargeting.
(cherry picked from commit e640692452)
Guard FormGroup control-map presence checks with safe own-property checks to avoid inherited/prototype collisions from reserved keys such as hasOwnProperty and toString.
This prevents:
- crashes from shadowed hasOwnProperty access paths
- incorrect early-return and existence behavior for prototype-named controls
Adds regression tests for prototype-shadowed keys covering:
- register/add with toString
- contains/get with hasOwnProperty
- setControl/removeControl with toString
- FormRecord behavior with hasOwnProperty
(cherry picked from commit f06b96d181)
Replace the custom 64-bit non-cryptographic combined DJB2 hashing implementation in HttpTransferCache with a robust, pure JavaScript, synchronous SHA-256 algorithm.
Using DJB2 is vulnerable to pre-image and second-preimage attacks due to its small 64-bit keyspace and mathematical simplicity. An attacker could craft colliding request inputs to poison the cache, potentially causing a CDN or the application to serve the wrong cached response to legitimate users.
SHA-256 provides strong cryptographic collision resistance, preventing cache key collision attacks. A custom synchronous implementation is required because the Web Crypto API (`crypto.subtle.digest`) is asynchronous, whereas the transfer cache state lookup and interceptor flow must operate synchronously.
Also, update the unit tests to dynamically verify the custom SHA-256 output against the native Web Crypto API.
Uses WeakRef + global.gc() to verify that destroyed effect consumers
become garbage-collectable when a non-live computed reads the same
producer.
The jasmine_test target is configured with node_options: --expose-gc.
GC tests are skipped in browser targets via isBrowser from
@angular/private/testing.
Made-with: Cursor
PR Close#68681
Calling `.hasOwnProperty()` on an object created with `Object.create(null)`
throws a TypeError because such objects have no prototype and therefore no
inherited `hasOwnProperty` method. Replace it with `Object.hasOwn()`, which
is a static method immune to prototype chain issues.
Adds a regression test covering null-prototype objects passed to
`toStylingKeyValueArray`.
(cherry picked from commit a786862c54)
This is more a hardening concern. Other non-nullish values were already throwing but here we make it explicit that undefined also throws.
(cherry picked from commit c5293c4c9d)
Reject non-script elements when reading the SSR transfer state payload by id.
This prevents attacker-controlled elements with a clobbered id from spoofing
hydration state.
(cherry picked from commit 6bde84fa8e)
Stop inheritance traversal before built-in prototype objects and only read `ɵcmp`/`ɵdir` when they are own properties of a super type. This prevents polluted inherited properties from being treated as Angular defs during inheritance merging.
Also adds regression tests covering polluted `Object.prototype.ɵdir` and `Object.prototype.ɵcmp` to ensure polluted host metadata is not inherited.
(cherry picked from commit e695379354)
Split the `ng` global interface into two interfaces:
* `ExternalCoreGlobalUtils` includes all the functionality which has been shipped in a long-lived Angular version externally and which is subject to the versioning constraints described above.
* `InternalCoreGlobalUtils` includes internal-only functionality which has **not** been shipped in a long-lived Angular version.
This split means that all APIs in `InternalCoreGlobalUtils` can be iterated and evolved at a much faster pace. Angular DevTools can support those features, and we can make breaking changes more-or-less whenever we want. The downside is that external Angular developers cannot take advantage of those APIs or else we would be subject to the same versioning constraint we're trying to avoid here.
This means we can use `InternalCoreGlobalUtils` as a kind of "beta" channel for new DevTools APIs. Once that functionality is validated and the design is stabilized, the feature can be moved into `ExternalCoreGlobalUtils` and made available for external Angular developers when we're ready to commit to the long-lived version constraint. This will hopefully help us strike a better balance between iterating on new APIs quickly and maintaining stable APIs for external Angular users.
(cherry picked from commit d069c55ab4)
By default, the `FetchBackend` on SSR will limit the response body size to 10 MB.
If the response body exceeds this limit, an error will be thrown.
This default value can be configured by providing by setting the `maxResponseBodySize` in `provideServerRendering`.
This is to prevent DoS on the server when loading large files
(cherry picked from commit 2acca1165d)
Fixes that we were registering DOM triggers even if the `@defer` block is set up to be rendered manually. This matches the behavior we already have for timer triggers.
Fixes#68800.
(cherry picked from commit abc61aaf7c)
Custom XML/XHTML namespaced elements (e.g., <xhtml:a>) fall back to the standard HTML namespace during element creation at compile-time/runtime. However, their property and security context lookups inside the schema registry were incorrectly performed using the full namespaced tag name (e.g., :xhtml:a), which bypassed the default a|href sanitization registry and incorrectly returned SecurityContext.NONE instead of SecurityContext.URL.
This commit introduces tag name normalization inside DomElementSchemaRegistry for custom namespaces (other than the built-in svg and math namespaces). Custom namespaced tag names are now normalized to their simple HTML element counterparts for all registry queries, ensuring that correct property schema validation and dynamic security sanitization rules (such as URL sanitization) are enforced at runtime.
PR Close#68868
Dynamic bindings to `href` and `xlink:href` attributes on SVG `<a>` elements (`<svg:a>`) were previously unmapped in the DOM security schema. As a result, they bypassed sanitization completely, creating a potential XSS vulnerability if bound to untrusted user inputs (e.g., `javascript:` URLs).
This fix mitigates this risk by:
1. Registering `href` and `xlink:href` on `<svg:a>` elements under the `SecurityContext.URL` context in both the compiler and core DOM security schemas.
2. Enabling template compilation to output runtime URL sanitization checks (`ɵɵsanitizeUrl`) on these attributes.
3. Adding regression and verification test cases to ensure dynamic SVG link bindings are safely sanitized at runtime while static values are correctly allowed.
PR Close#68868