Skip to content

build(deps): update dependency @angular/ssr to v20.3.21 [security]#1315

Merged
renovate[bot] merged 1 commit intomainfrom
renovate/npm-angular-ssr-vulnerability
Mar 31, 2026
Merged

build(deps): update dependency @angular/ssr to v20.3.21 [security]#1315
renovate[bot] merged 1 commit intomainfrom
renovate/npm-angular-ssr-vulnerability

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate Bot commented Feb 26, 2026

This PR contains the following updates:

Package Change Age Confidence
@angular/ssr 20.3.1320.3.21 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)

v20.3.21

Compare Source

@​angular/ssr
Commit Type Description
1dc6992a5 fix disallow x-forwarded-prefix starting with a backslash
0a2ff0b2b fix ensure unique values in redirect response Vary header
cdbac82a8 fix 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

Configuration

📅 Schedule: Branch creation - "" in timezone Europe/Madrid, Automerge - Between 09:00 AM and 09:59 PM, Monday through Friday ( * 9-21 * * 1-5 ) in timezone Europe/Madrid.

🚦 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 requested a review from davidlj95 as a code owner February 26, 2026 01:51
@renovate renovate Bot added dependencies Pull requests that update a dependency file javascript labels Feb 26, 2026
@renovate renovate Bot enabled auto-merge (squash) February 26, 2026 01:51
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.03%. Comparing base (6c64ad5) to head (c167d62).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1315   +/-   ##
=======================================
  Coverage   98.03%   98.03%           
=======================================
  Files         127      127           
  Lines         765      765           
  Branches       62       62           
=======================================
  Hits          750      750           
  Misses          8        8           
  Partials        7        7           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@renovate renovate Bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 3af614f to b5cf272 Compare March 5, 2026 19:50
@renovate renovate Bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from b5cf272 to 686821e Compare March 20, 2026 00:51
@renovate renovate Bot changed the title build(deps): update dependency @angular/ssr to v20.3.17 [security] build(deps): update dependency @angular/ssr to v20.3.21 [security] Mar 20, 2026
@renovate renovate Bot changed the title build(deps): update dependency @angular/ssr to v20.3.21 [security] build(deps): update dependency @angular/ssr to v20.3.21 [security] - autoclosed Mar 27, 2026
@renovate renovate Bot closed this Mar 27, 2026
auto-merge was automatically disabled March 27, 2026 01:02

Pull request was closed

@renovate renovate Bot deleted the renovate/npm-angular-ssr-vulnerability branch March 27, 2026 01:02
@renovate renovate Bot changed the title build(deps): update dependency @angular/ssr to v20.3.21 [security] - autoclosed build(deps): update dependency @angular/ssr to v20.3.21 [security] Mar 30, 2026
@renovate renovate Bot reopened this Mar 30, 2026
@renovate renovate Bot force-pushed the renovate/npm-angular-ssr-vulnerability branch 3 times, most recently from 2c3fd48 to 21f5c15 Compare March 31, 2026 13:05
@renovate renovate Bot enabled auto-merge (squash) March 31, 2026 13:05
@renovate renovate Bot force-pushed the renovate/npm-angular-ssr-vulnerability branch from 21f5c15 to c167d62 Compare March 31, 2026 20:54
@renovate renovate Bot merged commit 9f52947 into main Mar 31, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file javascript

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants