Skip to content

chore(deps): update dependency @angular/ssr to v21.2.3 [security]#2282

Open
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/npm-angular-ssr-vulnerability
Open

chore(deps): update dependency @angular/ssr to v21.2.3 [security]#2282
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/npm-angular-ssr-vulnerability

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate bot commented Feb 25, 2026

This PR contains the following updates:

Package Change Age Confidence
@angular/ssr 21.1.421.2.3 age confidence

GitHub Vulnerability Alerts

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)

v21.2.3

Compare Source

@​angular/cli
Commit Type Description
1505164bb fix use parsed package name for migrate-only updates
@​angular/build
Commit Type Description
75fa94cad fix alias createRequire banner import to avoid duplicate binding
d009aa1ec fix only use external packages for polyfills when no local files are present
@​angular/ssr
Commit Type Description
f3e0e82c2 fix disallow x-forwarded-prefix starting with a backslash
b8bcd59b4 fix ensure unique values in redirect response Vary header
84385411d fix support custom headers in redirect responses

v21.2.2

Compare Source

@​angular/cli
Commit Type Description
8447d9132 fix conditionally quote package names when adding dependencies based on host requirements
d2f209823 fix preserve exact version in ng add when requested
28f4d684a perf avoid redundant package version resolution in ng add
@​angular/build
Commit Type Description
06010294f fix allow any CHROME_BIN for vitest playwright provider
8dec0c62b fix normalize line endings for CSP hash generation
58688ebd7 fix pass process environment variables to prerender workers
4ca61647f fix resolve assets correctly during i18n prerendering

v21.2.1

Compare Source

@​angular/cli
Commit Type Description
ae4c28d00 fix correct dev dependency detection logic in ng add
465073bc1 fix disable npm update notifier in package manager host
36270634f fix ensure group members are updated to targeted version
d87dba6af fix ignore unknown files when formatting schematic changes
@​schematics/angular
Commit Type Description
72d466aa0 fix prevent adding test dependencies when minimal option is enabled
@​angular-devkit/build-angular
Commit Type Description
0019d1c8e fix update copy-webpack-plugin to v14.0.0
@​angular/build
Commit Type Description
6ad860863 fix bundle polyfills to preserve execution order in dev server
d17397375 fix conditionally allow vi.mock for non-relative imports
0d49f86ed fix resolve style include paths relative to ng-package.json in unit-test builder
584f6a2d9 fix treat empty browsers array as undefined in unit-test builder
6699cdc9b perf fix memory leak in ng serve with i18n
@​angular/ssr
Commit Type Description
43a9dfa66 fix improve header validation logic
dee3717b3 fix introduce DI token to signal route discovery process

v21.2.0

Compare Source

@​angular/cli
Commit Type Description
0dd04f289 feat add markdown files to Prettier's formatting list
fbae1b6ab feat automatic formatting files modified by schematics
91b9d281f feat integrate file formatting into update migrations
98a24d040 feat standardize MCP tools around workspace/project options
d9cd609c5 fix correctly parse scoped packages in yarn classic list output
5b05f2500 fix enable shell option for Prettier execution on Windows platforms
25b8a157d fix quote complex range specifiers in package manager
6f29a8c35 fix renamed files by their new path in the schematic workflow
201a036f2 fix simplify Angular version compatibility checks and add special handling for local builds of new major versions
cdd26bb66 fix validate package manager version using semver.valid and throw an error if invalid
bc363af8b perf optimize package manager discovery with stat-based probing
@​schematics/angular
Commit Type Description
aa7381efd feat add a '.prettierrc' file to generated workspaces and add Prettier as dev dependency
f80db6fb7 feat add ng-add support for Vitest browser providers
5d1df50d8 fix add actionable feedback to vitest-browser schematic
@​angular/build
Commit Type Description
ece30f235 feat add headless option to unit-test builder
cad7a7c0f feat run vitest browser with playwright with OS theme
0b4982720 fix adjust sourcemap sources when Vitest wrapper is bypassed
1f114a9e8 fix bundle setup files in unit-test builder for Vitest
fd5cb28c8 fix explicitly fail when using Vitest runtime mocking
dc899e8a5 fix normalize allowedHosts in dev-server
26bbea12f fix serve extensionless assets without transformation

v21.1.5

Compare Source

@​angular/ssr
Commit Type Description
8695d6063 fix prevent open redirect via X-Forwarded-Prefix header
e4d445ec6 fix validate host headers to prevent header-based SSRF

Configuration

📅 Schedule: Branch creation - "" in timezone Europe/London, Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, 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 enabled auto-merge (squash) February 25, 2026 22:47
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 3a706c5 to 3e59032 Compare February 26, 2026 09:12
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch 2 times, most recently from 5c8b40d to 21fc2e7 Compare February 26, 2026 16:27
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 21fc2e7 to 85cba30 Compare February 26, 2026 17:45
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 85cba30 to acb4932 Compare February 27, 2026 00:48
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 19d2e3f to cb4d997 Compare March 3, 2026 09:06
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 4ec8a82 to 9d1fa87 Compare March 10, 2026 19:24
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch 2 times, most recently from 24d0959 to fa2cf6d Compare March 11, 2026 10:12
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 9acef7c to b902f96 Compare March 12, 2026 11:51
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from b902f96 to 89d20ba Compare March 13, 2026 10:26
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 89d20ba to 9ae1e4e Compare March 13, 2026 11:50
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 9ae1e4e to f67252f Compare March 13, 2026 12:27
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from f67252f to b508f97 Compare March 13, 2026 13:31
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from b508f97 to 8a5cd22 Compare March 13, 2026 14:24
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 8a5cd22 to e28086f Compare March 13, 2026 15:12
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from e28086f to 70842e6 Compare March 13, 2026 16:10
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 70842e6 to 607f674 Compare March 13, 2026 17:10
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 607f674 to 811309c Compare March 13, 2026 18:52
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch 2 times, most recently from a9c17c5 to 7252dcb Compare March 16, 2026 10:53
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 7252dcb to 017156b Compare March 16, 2026 18:33
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 017156b to c707f11 Compare March 16, 2026 23:06
@renovate renovate bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from c707f11 to a17503a Compare March 17, 2026 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants