Apr 9, 2026·6 min read·7 visits
FrontMCP (< 2.3.0) blindly resolves OpenAPI `$ref` pointers using `@apidevtools/json-schema-ref-parser`, resulting in high-impact SSRF and LFI vulnerabilities via unrestricted `http://` and `file://` protocols.
A high-severity vulnerability exists in the `mcp-from-openapi` library of the FrontMCP framework. Versions prior to 2.3.0 fail to restrict protocol schemes and network destinations when dereferencing OpenAPI `$ref` pointers. This flaw allows unauthenticated Server-Side Request Forgery (SSRF) and Local File Inclusion (LFI), enabling attackers to access internal network services, cloud metadata endpoints, and arbitrary local files.
The FrontMCP framework utilizes the mcp-from-openapi library to process and integrate external OpenAPI specifications. This processing phase involves parsing structured JSON or YAML schemas and dereferencing $ref pointers to assemble a complete, flat schema document. The dereferencing operation is delegated to the @apidevtools/json-schema-ref-parser library during the application initialization sequence.
A Server-Side Request Forgery (SSRF) vulnerability, classified under CWE-918, exists within mcp-from-openapi versions prior to 2.3.0. The vulnerability stems from the insecure invocation of the underlying schema reference parser. The application invokes the parsing library without defining protocol restrictions or hostname boundaries, instructing the parser to inherently trust and follow any uniform resource identifier (URI) supplied in a $ref node.
This implementation oversight creates a direct attack vector for unauthenticated exploitation. Attackers who can supply or influence the OpenAPI specification processed by FrontMCP can trigger unauthorized network requests from the server. Additionally, the parser's default support for the file:// protocol introduces a Local File Inclusion (LFI) vector, broadening the impact to direct local system compromise.
The root cause of CVE-2026-39885 lies in the OpenAPIToolGenerator.initialize() method within the mcp-from-openapi codebase. When initializing a new tool generator, the class calls import_json_schema_ref_parser.default.dereference() and passes the raw, unvalidated OpenAPI document as the primary argument. No secondary options object is provided to govern the parser's behavior.
The @apidevtools/json-schema-ref-parser library relies on internal resolvers for different URI protocols. By default, it enables the HTTP, HTTPS, and FILE resolvers. When the parser encounters a JSON pointer (e.g., {"$ref": "http://example.com/schema"}), it delegates the fetch operation to the corresponding resolver. Because mcp-from-openapi does not override this default configuration, the parser executes external requests and local file reads unconditionally.
When a malicious $ref value is processed, the Node.js process executes an HTTP GET request or filesystem stream read on the target URI. The contents returned by this operation are then serialized and embedded into the final schema structure in memory. The execution flow directly exposes internal resources to the application layer.
The following diagram maps the execution path of the vulnerability:
The vulnerable implementation in mcp-from-openapi (versions < 2.3.0) executes the parser dereferencing step with a single argument. This code path lacks the secondary options dictionary required to disable or restrict specific resolution plugins.
// Vulnerable Implementation
this.dereferencedDocument = await import_json_schema_ref_parser.default.dereference(
JSON.parse(JSON.stringify(this.document))
);The patch introduced in commit b69f4d8ed3edc7de3e85ddbdcc78910339510d53 rectifies this by wrapping the resolution logic in a customized configuration. The developers introduced a refResolution property within a new loadOptions configuration object. This patch enforces a default-deny policy for the file protocol and applies strict CIDR block filtering for network requests.
// Patched Implementation (Conceptual based on commit data)
const options = {
resolve: {
file: false, // Disables local file resolution completely
http: customHttpResolver,
https: customHttpsResolver
}
};
this.dereferencedDocument = await import_json_schema_ref_parser.default.dereference(
JSON.parse(JSON.stringify(this.document)),
options
);The custom HTTP resolvers evaluate the target hostname against a rigorous blocklist before initiating the socket connection. The patch explicitly blocks 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, and 169.254.0.0/16. It also drops requests targeting local IPv6 spaces (::1, fd00::/8) and specific hostnames like localhost and metadata.google.internal. This systematic denial of private address spaces effectively neutralizes the internal SSRF vector.
Exploitation requires the attacker to supply a crafted OpenAPI document to an application running a vulnerable version of frontmcp or mcp-from-openapi. The specific delivery mechanism depends on how the application ingests OpenAPI specifications. If the application exposes an API endpoint to upload or register new tool schemas, the attacker can submit the malicious payload directly over the network.
To execute an SSRF attack, the attacker crafts a $ref pointing to an internal infrastructure component. In cloud environments, the primary target is the Instance Metadata Service (IMDS). The payload structure embeds the reference within a standard OpenAPI block, such as a path response definition.
The following Proof of Concept demonstrates the vulnerability. The local web server simulates the internal target. When the OpenAPIToolGenerator parses the specification, it performs a GET request to the local server, logging the SSRF hit.
const http = require('http');
const { OpenAPIToolGenerator } = require('mcp-from-openapi');
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: {
responses: {
'200': {
content: {
'application/json': {
schema: { '$ref': 'http://127.0.0.1:9997/ssrf-proof' }
}
}
}
}
}
}
}
};
const gen = new OpenAPIToolGenerator(spec, { validate: false });
await gen.initialize();
srv.close();
});The Local File Inclusion (LFI) vector operates identically but leverages the file:// scheme. An attacker injects {"$ref": "file:///etc/passwd"} into the schema. Upon parsing, the library reads the file from the local disk and attempts to parse it as JSON or YAML, embedding the raw string or generating a parsing error that exposes file contents via stack traces.
The vulnerability carries a CVSS v3.1 base score of 7.5, characterized by the vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N. The primary driver for this severity is the high confidentiality impact. The absence of authentication and user interaction prerequisites makes the vulnerability highly reliable to exploit in applications that dynamically load user-supplied tool schemas.
In AWS, GCP, or Azure environments, the SSRF vector facilitates the retrieval of cloud instance metadata. By targeting http://169.254.169.254/latest/meta-data/iam/security-credentials/, an attacker retrieves short-lived IAM credentials assigned to the underlying compute instance. This pivot often leads to comprehensive account compromise, allowing attackers to access S3 buckets, internal databases, or additional compute resources.
The LFI vector presents severe risks for containerized and on-premises deployments. Attackers can extract sensitive configuration files, environment variables located in /proc/self/environ, or private cryptographic keys stored on the filesystem. The combination of unrestricted LFI and internal network mapping capabilities grants the attacker extensive visibility into the target infrastructure.
To remediate CVE-2026-39885, software development teams must upgrade their FrontMCP dependencies immediately. Specifically, the frontmcp, @frontmcp/sdk, and @frontmcp/adapters packages must be updated to version 1.0.4 or higher. This release includes the patched mcp-from-openapi library at version 2.3.0, which enforces the blocklist by default.
Administrators should configure explicit network boundaries using the newly introduced refResolution options. By setting an allowedHosts array within loadOptions, developers enforce a strict allowlist. This defense-in-depth measure guarantees that schema resolution only occurs against trusted, predefined domains, overriding the default blocklist logic.
In environments where immediate patching is unfeasible, infrastructure-level mitigations are required. Operations teams must enforce strict egress network filtering on the container or virtual machine hosting the FrontMCP application. Blocking outbound HTTP connections to 169.254.169.254 and enforcing IMDSv2 (which requires specific HTTP headers) neutralizes the cloud metadata SSRF vector. Local LFI vectors can be mitigated by running the application within a read-only container filesystem with minimal mounted secrets.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
mcp-from-openapi FrontMCP | < 2.3.0 | 2.3.0 |
frontmcp FrontMCP | < 1.0.4 | 1.0.4 |
@frontmcp/sdk FrontMCP | < 1.0.4 | 1.0.4 |
@frontmcp/adapters FrontMCP | < 1.0.4 | 1.0.4 |
| Attribute | Detail |
|---|---|
| CWE | CWE-918 (Server-Side Request Forgery) |
| Attack Vector | Network |
| CVSS Base Score | 7.5 (High) |
| Impact | High Confidentiality, Local File Inclusion |
| Exploit Status | Proof of Concept (PoC) |
| KEV Status | Not Listed |
The software does not properly restrict network requests or file access when dereferencing user-supplied URI structures, leading to SSRF and LFI.