Skip to content

chore(deps): update dependency @angular/ssr to v20.3.21 [security] - autoclosed#124

Closed
renovate[bot] wants to merge 1 commit intomainfrom
renovate/npm-angular-ssr-vulnerability
Closed

chore(deps): update dependency @angular/ssr to v20.3.21 [security] - autoclosed#124
renovate[bot] wants to merge 1 commit intomainfrom
renovate/npm-angular-ssr-vulnerability

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate bot commented Sep 11, 2025

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
@angular/ssr 20.1.220.3.21 age confidence

GitHub Vulnerability Alerts

CVE-2025-59052

Impact

Angular uses a DI container (the "platform injector") to hold request-specific state during server-side rendering. For historical reasons, the container was stored as a JavaScript module-scoped global variable. When multiple requests are processed concurrently, they could inadvertently share or overwrite the global injector state.

In practical terms, this can lead to one request responding with data meant for a completely different request, leaking data or tokens included on the rendered page or in response headers. As long as an attacker had network access to send any traffic that received a rendered response, they may have been able to send a large number of requests and then inspect the responses for information leaks.

The following APIs were vulnerable and required SSR-only breaking changes:

  • bootstrapApplication: This function previously implicitly retrieved the last platform injector that was created. It now requires an explicit BootstrapContext in a server environment. This function is only used for standalone applications. NgModule-based applications are not affected.
  • getPlatform: This function previously returned the last platform instance that was created. It now always returns null in a server environment.
  • destroyPlatform: This function previously destroyed the last platform instance that was created. It's now a no-op when called in a server environment.

For bootstrapApplication, the framework now provides a new argument to the application's bootstrap function:

// Before:
const bootstrap = () => bootstrapApplication(AppComponent, config);

// After:
const bootstrap = (context: BootstrapContext) =>
  bootstrapApplication(AppComponent, config, context);

As is usually the case for changes to Angular, an automatic schematic will take care of these code changes as part of ng update:

# For apps on Angular v20:
ng update @​angular/cli @​angular/core

# For apps on Angular v19:
ng update @​angular/cli@19 @​angular/core@19

# For apps on Angular v18:
ng update @​angular/cli@18 @​angular/core@18

The schematic can also be invoked explicitly if the version bump was pulled in independently:

# For apps on Angular v20:
ng update @​angular/core --name add-bootstrap-context-to-server-main

# For apps on Angular v19:
ng update @​angular/core@19 --name add-bootstrap-context-to-server-main

# For apps on Angular v18:
ng update @​angular/core@18 --name add-bootstrap-context-to-server-main

For applications that still use CommonEngine, the bootstrap property in CommonEngineOptions also gains the same context argument in the patched versions of Angular.

In local development (ng serve), Angular CLI triggered a codepath for Angular's "JIT" feature on the server even in applications that weren't using it in the browser. The codepath introduced async behavior between platform creation and application bootstrap, triggering the race condition even if an application didn't explicitly use getPlatform or custom async logic in bootstrap. Angular applications should never run in this mode outside of local development.

Patches

The issue has been patched in all active release lines as well as in the v21 prerelease:

  • @angular/platform-server: 21.0.0-next.3

  • @angular/platform-server: 20.3.0

  • @angular/platform-server: 19.2.15

  • @angular/platform-server: 18.2.14

  • @angular/ssr: 21.0.0-next.3

  • @angular/ssr: 20.3.0

  • @angular/ssr: 19.2.16

  • @angular/ssr: 18.2.21

Workarounds

  • Disable SSR via Server Routes (v19+) or builder options.
  • Remove any asynchronous behavior from custom bootstrap functions.
  • Remove uses of getPlatform() in application code.
  • Ensure that the server build defines ngJitMode as false.

References

CVE-2025-62427

Impact

The vulnerability is a Server-Side Request Forgery (SSRF) flaw within the URL resolution mechanism of Angular's Server-Side Rendering package (@angular/ssr).

The function createRequestUrl uses the native URL constructor. When an incoming request path (e.g., originalUrl or url) begins with a double forward slash (//) or backslash (\\), the URL constructor treats it as a schema-relative URL. This behavior overrides the security-intended base URL (protocol, host, and port) supplied as the second argument, instead resolving the URL against the scheme of the base URL but adopting the attacker-controlled hostname.

This allows an attacker to specify an external domain in the URL path, tricking the Angular SSR environment into setting the page's virtual location (accessible via DOCUMENT or PlatformLocation tokens) to this attacker-controlled domain. Any subsequent relative HTTP requests made during the SSR process (e.g., using HttpClient.get('assets/data.json')) will be incorrectly resolved against the attacker's domain, forcing the server to communicate with an arbitrary external endpoint.

Exploit Scenario

A request to http://localhost:4200//attacker-domain.com/some-page causes Angular to believe the host is attacker-domain.com. A relative request to api/data then becomes a server-side request to http://attacker-domain.com/api/data.

Patches

  • @angular/ssr 19.2.18
  • @angular/ssr 20.3.6
  • @angular/ssr 21.0.0-next.8

Mitigation

The application's internal location must be robustly determined from the incoming request. The fix requires sanitizing or validating the request path to prevent it from being interpreted as a schema-relative URL (i.e., ensuring it does not start with //).

Server-Side Middleware

If you can't upgrade to a patched version, implement a middleware on the Node.js/Express server that hosts the Angular SSR application to explicitly reject or sanitize requests where the path begins with a double slash (//).

Example (Express/Node.js):

// Place this middleware before the Angular SSR handler
app.use((req, res, next) => {
  if (req.originalUrl?.startsWith('//')) {
    // Sanitize by forcing a single slash
    req.originalUrl = req.originalUrl.replace(/^\/\/+/, '/');
    req.url = req.url.replace(/^\/\/+/, '/');
  }
  next();
});

References

CVE-2026-27738

An Open Redirect vulnerability exists in the internal URL processing logic in Angular SSR. The logic normalizes URL segments by stripping leading slashes; however, it only removes a single leading slash.

When an Angular SSR application is deployed behind a proxy that passes the X-Forwarded-Prefix header, an attacker can provide a value starting with three slashes (e.g., ///evil.com).

  1. The application processes a redirect (e.g., from a router redirectTo or i18n locale switch).
  2. Angular receives ///evil.com as the prefix.
  3. It strips one slash, leaving //evil.com.
  4. The resulting string is used in the Location header.
  5. Modern browsers interpret // as a protocol-relative URL, redirecting the user from https://your-app.com to https://evil.com.

Impact

This vulnerability allows attackers to conduct large-scale phishing and SEO hijacking:

  • Scale: A single request can poison a high-traffic route, impacting all users until the cache expires.
  • SEO Poisoning: Search engine crawlers may follow and index these malicious redirects, causing the legitimate site to be delisted or associated with malicious domains.
  • Trust: Because the initial URL belongs to the trusted domain, users and security tools are less likely to flag the redirect as malicious.

Attack Preconditions

  • The application must use Angular SSR.
  • The application must have routes that perform internal redirects.
  • The infrastructure (Reverse Proxy/CDN) must pass the X-Forwarded-Prefix header to the SSR process without sanitization.
  • The cache must not vary on the X-Forwarded-Prefix header.

Patches

  • 21.2.0-rc.1
  • 21.1.5
  • 20.3.17
  • 19.2.21

Workarounds

Until the patch is applied, developers should sanitize the X-Forwarded-Prefix header in theirserver.ts before the Angular engine processes the request:

app.use((req, res, next) => {
  const prefix = req.headers['x-forwarded-prefix']?.trim();
  if (prefix) {
    // Sanitize by removing all leading slashes
    req.headers['x-forwarded-prefix'] = prefix.replace(/^[/\\]+/, '/');
  }
  next();
});

Resources

CVE-2026-27739

A Server-Side Request Forgery (SSRF) vulnerability has been identified in the Angular SSR request handling pipeline. The vulnerability exists because Angular’s internal URL reconstruction logic directly trusts and consumes user-controlled HTTP headers specifically the Host and X-Forwarded-* family to determine the application's base origin without any validation of the destination domain.

Specifically, the framework didn't have checks for the following:

  • Host Domain: The Host and X-Forwarded-Host headers were not checked to belong to a trusted origin. This allows an attacker to redefine the "base" of the application to an arbitrary external domain.
  • Path & Character Sanitization: The X-Forwarded-Host header was not checked for path segments or special characters, allowing manipulation of the base path for all resolved relative URLs.
  • Port Validation: The X-Forwarded-Port header was not verified as numeric, leading to malformed URI construction or injection attacks.

This vulnerability manifests in two primary ways:

  • Implicit Relative URL Resolution: Angular's HttpClient resolves relative URLs against this unvalidated and potentially malformed base origin. An attacker can "steer" these requests to an external server or internal service.
  • Explicit Manual Construction: Developers injecting the REQUEST object to manually construct URLs (for fetch or third-party SDKs) directly inherit these unsanitized values. By accessing the Host / X-Forwarded-* headers, the application logic may perform requests to attacker-controlled destinations or malformed endpoints.

Impact

When successfully exploited, this vulnerability allows for arbitrary internal request steering. This can lead to:

  • Credential Exfiltration: Stealing sensitive Authorization headers or session cookies by redirecting them to an attacker's server.
  • Internal Network Probing: Accessing and transmitting data from internal services, databases, or cloud metadata endpoints (e.g., 169.254.169.254) not exposed to the public internet.
  • Confidentiality Breach: Accessing sensitive information processed within the application's server-side context.

Attack Preconditions

  • The victim application must use Angular SSR (Server-Side Rendering).
  • The application must perform HttpClient requests using relative URLs OR manually construct URLs using the unvalidated Host / X-Forwarded-* headers using the REQUEST object.
  • Direct Header Access: The application server is reachable by an attacker who can influence these headers without strict validation from a front-facing proxy.
  • Lack of Upstream Validation: The infrastructure (Cloud, CDN, or Load Balancer) does not sanitize or validate incoming headers.

Patches

  • 21.2.0-rc.1
  • 21.1.5
  • 20.3.17
  • 19.2.21

Workarounds

  • Use Absolute URLs: Avoid using req.headers for URL construction. Instead, use trusted variables for your base API paths.
  • Implement Strict Header Validation (Middleware): If you cannot upgrade immediately, implement a middleware in your server.ts to enforce numeric ports and validated hostnames.
const ALLOWED_HOSTS = new Set(['your-domain.com']);

app.use((req, res, next) => {
  const hostHeader = (req.headers['x-forwarded-host'] ?? req.headers['host'])?.toString();
  const portHeader = req.headers['x-forwarded-port']?.toString();

  if (hostHeader) {
    const hostname = hostHeader.split(':')[0];
    // Reject if hostname contains path separators or is not in allowlist
    if (/^[a-z0-9.:-]+$/i.test(hostname) || 
       (!ALLOWED_HOSTS.has(hostname) && hostname !== 'localhost')) {
      return res.status(400).send('Invalid Hostname');
    }
  }

  // Ensure port is strictly numeric if provided
  if (portHeader && !/^\d+$/.test(portHeader)) {
    return res.status(400).send('Invalid Port');
  }

  next();
});

References

CVE-2026-33397

An Open Redirect vulnerability exists in @angular/ssr due to an incomplete fix for CVE-2026-27738. While the original fix successfully blocked multiple leading slashes (e.g., ///), the internal validation logic fails to account for a single backslash (\) bypass.

When an Angular SSR application is deployed behind a proxy that passes the X-Forwarded-Prefix header:

  • An attacker provides a value starting with a single backslash (e.g., \evil.com).
  • The internal validation failed to flag the single backslash as invalid.
  • The application prepends a leading forward slash, resulting in a Location header containing /\evil.com.
  • Modern browsers interpret the /\ sequence as //, treating it as a protocol-relative URL and redirecting the user to the attacker-controlled domain.

Furthermore, the response lacks the Vary: X-Forwarded-Prefix header, allowing the malicious redirect to be stored in intermediate caches (Web Cache Poisoning).

Impact

This vulnerability allows attackers to conduct large-scale phishing and SEO hijacking:

  • Scale: A single request can poison a high-traffic route, impacting all users until the cache expires.
  • SEO Poisoning: Search engine crawlers may follow and index these malicious redirects, causing the legitimate site to be delisted or associated with malicious domains.
  • Trust: Because the initial URL belongs to the trusted domain, users and security tools are less likely to flag the redirect as malicious.

Patches

  • 22.0.0-next.2
  • 21.2.3
  • 20.3.21

Workarounds

Until the patch is applied, developers should sanitize the X-Forwarded-Prefix header in their server.ts before the Angular engine processes the request:

app.use((req, res, next) => {
  const prefix = req.headers['x-forwarded-prefix'];
  if (typeof prefix === 'string') {
    // Sanitize by removing all leading forward and backward slashes
    req.headers['x-forwarded-prefix'] = prefix.trim().replace(/^[/\\]+/, '/');
  }
  next();
});

References


Release Notes

angular/angular-cli (@​angular/ssr)

v20.3.21: 20.3.21

Compare Source

@​angular/ssr
Commit Description
fix - 1dc6992a5 disallow x-forwarded-prefix starting with a backslash
fix - 0a2ff0b2b ensure unique values in redirect response Vary header
fix - cdbac82a8 support custom headers in redirect responses

v20.3.20

Compare Source

@​angular/build
Commit Type Description
0fd6823af fix pass process environment variables to prerender workers

v20.3.19

Compare Source

@​angular-devkit/build-angular
Commit Type Description
0299b4d1a fix update copy-webpack-plugin to v14.0.0

v20.3.18

Compare Source

@​angular-devkit/core
Commit Type Description
39596d529 fix update ajv to 8.18.0
@​angular/build
Commit Type Description
f668e2778 fix update rollup to 4.59.0

v20.3.17

Compare Source

@​angular/ssr
Commit Type Description
8700e18d7 fix prevent open redirect via X-Forwarded-Prefix header
67582a946 fix validate host headers to prevent header-based SSRF

v20.3.16

Compare Source

@​angular/cli
Commit Type Description
656888a25 fix update dependency @​modelcontextprotocol/sdk to v1.26.0

v20.3.15

Compare Source

@​angular/cli
Commit Type Description
795d65413 fix update pacote to v21.0.4
@​angular-devkit/build-angular
Commit Type Description
ffc72cbc5 fix update webpack to version 5.104.1

v20.3.14

Compare Source

@​angular/cli
Commit Type Description
ff366499e fix update dependency @​modelcontextprotocol/sdk to v1.25.2

v20.3.13

Compare Source

@​angular/cli
Commit Type Description
cfbb61602 fix update @modelcontextprotocol/sdk to v1.24.0

v20.3.12

Compare Source

@​angular/build
Commit Type Description
25bb7e65c fix ensure correct URL joining for prerender routes
@​angular/ssr
Commit Type Description
cceb86296 fix handle X-Forwarded-Prefix and APP_BASE_HREF in redirects
1abe68ad8 fix prevent redirect loop with encoded query parameters

v20.3.11

Compare Source

@​angular/build
Commit Type Description
8053f2d92 fix ensure ɵgetOrCreateAngularServerApp is always defined after errors

v20.3.10

Compare Source

@​schematics/angular
Commit Type Description
c854a719b fix correct tsconfig.spec.json include for spec files
@​angular/build
Commit Type Description
b3908f68e fix do not remove @angular/localize when having external packages (#​31721)

v20.3.9

Compare Source

@​angular/ssr
Commit Type Description
08e07e338 fix improve locale handling in app-engine
683697ebc fix improve route matching for wildcard routes

v20.3.8

Compare Source

@​angular-devkit/build-angular
Commit Type Description
813cba9b9 fix expand jest and jest-environment-jsdom to allow version 30
@​angular/build
Commit Type Description
542973ab0 fix add adapters to new reporter
f0885691d fix ensure locale data plugin runs before other plugins
45e498f95 fix handle redirects from guards during prerendering

v20.3.7

Compare Source

@​angular-devkit/schematics
Commit Type Description
a31533cf4 fix respect --force option when schematic contains host.create
@​angular/build
Commit Type Description
8cdda111c fix resolve Angular locale data namespace in esbuild
5847ccc54 fix update vite to 7.11.1
@​angular/ssr
Commit Type Description
3a28fb6a1 fix correctly handle routes with matrix parameters
5db6d6487 fix ensure server-side navigation triggers a redirect

v20.3.6

Compare Source

@​angular/ssr
Commit Type Description
5271547c8 fix prevent malicious URL from overriding host

v20.3.5

Compare Source

@​angular/build
Commit Type Description
7f7140680 fix cleanup karma temporary directory after process exit

v20.3.4

Compare Source

@​schematics/angular
Commit Type Description
c94bf7ff0 fix Out of the box support for PM2
465436c9f fix use bracket notation for process.env['pm_id']
@​angular-devkit/build-angular
Commit Type Description
bc6b63114 fix mark InjectionToken as pure for improved tree-shaking
@​angular/build
Commit Type Description
e510ff828 fix mark InjectionToken as pure for improved tree-shaking

v20.3.3

Compare Source

@​schematics/angular
Commit Type Description
b7f92da78 fix add __screenshots__/ to .gitignore
@​angular/ssr
Commit Type Description
a4c9a2007 fix avoid retaining rendered HTML in memory post-request

v20.3.2

Compare Source

v20.3.1

Compare Source

@​angular/build
Commit Type Description
be60be499 fix add timestamp to bundle generation log
d60f4e53d fix update vite to version 7.1.5

v20.3.0

Compare Source

Breaking Changes

@​angular/ssr
  • The server-side bootstrapping process has been changed to eliminate the reliance on a global platform injector.

    Before:

    const bootstrap = () => bootstrapApplication(AppComponent, config);

    After:

    const bootstrap = (context: BootstrapContext) =>
      bootstrapApplication(AppComponent, config, context);
@​schematics/angular
Commit Type Description
ef20a278d fix align labels in ai-config schema
@​angular/cli
Commit Type Description
f6ad41c13 fix improve bun lockfile detection and optimize lockfile checks
@​angular-devkit/build-angular
Commit Type Description
1a7890873 fix avoid extra tick in SSR builds
@​angular/build
Commit Type Description
5d46d6ec1 fix preserve names in esbuild for improved debugging in dev mode
@​angular/ssr
Commit Type Description
7eacb4187 feat introduce BootstrapContext for isolated server-side rendering

v20.2.2

Compare Source

@​angular/cli
Commit Type Description
a793bbc47 fix don't set a default for array options when length is 0
2736599e2 fix set process title when running architect commands
@​angular/build
Commit Type Description
5c2abffea fix avoid extra tick in SSR dev-server builds
f3c826853 fix maintain media output hashing with vitest unit-testing

v20.2.1

Compare Source

@​angular/cli
Commit Type Description
3b693e09e fix correctly set default array values
@​schematics/angular
Commit Type Description
6937123a3 fix directly resolve karma config template in migration
5d6dd4425 fix prevent AI config schematic from failing when 'none' and other AI tools are selected
@​angular-devkit/schematics-cli
Commit Type Description
e93919dea fix correctly set default array values
@​angular/build
Commit Type Description
06a6ddc10 fix correct JS/TS file paths when running under Bazel
b6816b0cb fix ensure karma polyfills reporter factory returns a value

v20.2.0

Compare Source

@​angular/cli
Commit Type Description
b4de9a1bf feat add --experimental-tool option to mcp command
755ba70fd feat add --local-only option to mcp command
59d7ef343 feat add --read-only option to mcp command
4e92eb6f1 feat add modernize tool to the MCP server
a3b25f675 fix add choices to command line parser when type is array and has an enum
e19eee614 fix address Node.js deprecation DEP0190
4ee6f327a fix apply default to array types
8ba6b0bcc fix use correct path for MCP get_best_practices tool
@​schematics/angular
Commit Type Description
2e3cfd598 feat add migration to remove default Karma configurations
d80dae276 feat add schematics to generate ai context files.
ffe6fb916 fix allow AI config prompt to be skipped without selecting a value
ae2802b7d fix improve AI config prompt wording
b017f84fd fix improve coverage directory handling for Karma configuration comparisons
6a79f9a75 fix zoneless is now stable
@​angular-devkit/schematics
Commit Type Description
c43504d8d fix address Node.js deprecation DEP0190
@​angular/build
Commit Type Description
fb06bb505 feat add headless mode for vitest browser mode

v20.1.6

Compare Source

@​schematics/angular
Commit Type Description
584bc1d41 fix add extra prettier config
02b0506fd fix correct configure the typeSeparator in the library schematic

v20.1.5

Compare Source

@​angular/cli
Commit Type Description
48ca04474 fix cache MCP best practices content and add tool annotations

v20.1.4

Compare Source

@​angular/cli
Commit Type Description
2d753cc62 fix

Configuration

📅 Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot changed the title fix(deps): update dependency @angular/ssr to v19.2.16 [security] chore(deps): update dependency @angular/ssr to v19.2.16 [security] Sep 25, 2025
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from ac13ac3 to 88f3f4d Compare September 25, 2025 14:15
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 88f3f4d to 222227e Compare October 16, 2025 22:34
@renovate renovate bot changed the title chore(deps): update dependency @angular/ssr to v19.2.16 [security] chore(deps): update dependency @angular/ssr to v19.2.18 [security] Oct 16, 2025
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 222227e to c5192b4 Compare October 25, 2025 15:01
@renovate renovate bot changed the title chore(deps): update dependency @angular/ssr to v19.2.18 [security] chore(deps): update dependency @angular/ssr to v20.3.6 [security] Oct 25, 2025
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from c5192b4 to 7efed4a Compare November 6, 2025 07:09
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 7efed4a to f135233 Compare December 19, 2025 06:30
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from f135233 to 1dac423 Compare December 31, 2025 15:53
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 1dac423 to fb2de1a Compare February 12, 2026 10:36
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from fb2de1a to d35f276 Compare February 26, 2026 02:48
@renovate renovate bot changed the title chore(deps): update dependency @angular/ssr to v20.3.6 [security] chore(deps): update dependency @angular/ssr to v20.3.17 [security] Feb 26, 2026
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch 2 times, most recently from 22bc503 to 288c28c Compare March 13, 2026 14:38
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 288c28c to 5ebc40e Compare March 20, 2026 01:08
@renovate renovate bot changed the title chore(deps): update dependency @angular/ssr to v20.3.17 [security] chore(deps): update dependency @angular/ssr to v20.3.21 [security] Mar 20, 2026
@renovate renovate bot changed the title chore(deps): update dependency @angular/ssr to v20.3.21 [security] chore(deps): update dependency @angular/ssr to v20.3.21 [security] - autoclosed Mar 27, 2026
@renovate renovate bot closed this Mar 27, 2026
@renovate renovate bot deleted the renovate/npm-angular-ssr-vulnerability branch March 27, 2026 01:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants