🛡️ GHSA-8q49-2h5h-434x — adapters

⚪ Unknown ✅ No Known Exploit CWE-918 OSV
N/A
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

FrontMCP: Server-Side Request Forgery (SSRF) in the OpenAPI adapter spec-change poller

Summary

The OpenAPI adapter's spec-change poller (OpenApiSpecPoller) re-fetched the

configured spec url on a timer using a raw global fetch(), bypassing the SSRF

guard (safeFetch / assertUrlSafe) that OpenAPIToolGenerator.fromURL() applies

to the initial spec load. As a result, the pinning/DNS-resolution hardening delivered

via mcp-from-openapi >= 2.5.0 (advisory GHSA-65h7-9wrw-629c) protected the initial

load but not the recurring poll of the same URL. When polling is enabled against

an untrusted or attacker-influenceable spec URL, this is an unguarded SSRF vector.

Details

The initial spec load is guarded. OpenapiAdapter resolves a secure refResolution

policy and passes it to the guarded loader:

```ts

// libs/adapters/src/openapi/openapi.adapter.ts — initializeGenerator()

return await OpenAPIToolGenerator.fromURL(this.options.url, {

// ...

followRedirects: this.options.loadOptions?.followRedirects ?? false,

refResolution, // secure default: external $refs off, internal targets blocked

});

```

But the poller — which re-fetches the same URL on every interval — did not:

```ts

// libs/adapters/src/openapi/openapi-spec-poller.ts — doFetch() (vulnerable, <= 1.5.5)

const controller = new AbortController();

const timeout = setTimeout(() => controller.abort(), this.fetchTimeoutMs);

try {

const response = await fetch(this.url, { // <-- raw global fetch, no SSRF guard

headers,

signal: controller.signal,

});

// ...hash the body, fire onChanged...

}

```

Because doFetch() never called safeFetch, none of the guard's protections applied

to the polled request:

  • no allow-list / block-list enforcement (allowedHosts / blockedHosts);
  • no internal/private/loopback/link-local/CGNAT/cloud-metadata IP blocking;
  • no DNS resolution of the hostname (so a DNS name that resolves to an internal IP,

e.g. http://127.0.0.1.nip.io/, was reached);

  • no connection pinning to the validated IP (DNS-rebinding TOCTOU);
  • no per-hop re-validation of HTTP redirects.

This is the identical threat model to fromURL() / external $ref resolution

(GHSA-65h7-9wrw-629c), applied to a request path that the fix for that advisory did

not cover.

Impact

A server that enables spec polling against an untrusted or attacker-influenceable

spec URL will, on every poll interval, issue a server-side GET to whatever host the

URL (or a DNS name it resolves to, or a redirect it returns) points at — including

internal-only addresses unreachable from the public internet. Consequences include:

  • reading cloud-instance metadata endpoints (e.g. 169.254.169.254) — credential /

token theft;

  • probing and reaching internal services and private-range hosts (internal network

scanning);

  • DNS-rebinding to swap a public host for an internal one between validation and

connection.

The poller issues GET requests only, so the primary impact is confidentiality

(reaching and reading internal endpoints); the fetched body is content-hashed to

detect change and the subsequent tool rebuild goes back through the guarded

fromURL() path.

Preconditions

Exploitation requires both:

1. polling.enabled: true on an OpenapiAdapter (polling is off by default and

requires the URL-based url option, not an inline spec); and

2. the spec url is untrusted / attacker-influenceable (e.g. it is derived from user

input, a tenant-supplied value, or otherwise not a fixed trusted constant), or an

otherwise-trusted spec host is attacker-controlled or can redirect.

Servers that poll a fixed, trusted, first-party spec URL are not exposed in practice,

though they still benefit from the guard as defense-in-depth.

Proof of concept

```ts

import { OpenapiAdapter } from '@frontmcp/adapters';

// url is attacker-influenceable and points (directly, via DNS, or via redirect)

// at an internal target; polling re-fetches it every interval.

const adapter = OpenapiAdapter.init({

name: 'evil',

url: 'http://169.254.169.254/latest/meta-data/', // or http://127.0.0.1.nip.io/...

polling: { enabled: true, intervalMs: 5000 },

});

await adapter.fetch(); // initial load IS guarded (blocked)

adapter.startPolling(); // <= 1.5.5: each poll issues an UNGUARDED GET to the internal target

```

On <= 1.5.5 the timed poll reaches the internal address. On the patched version the

poll fails closed (no request is made; the failure is logged) exactly as the initial

load does.

Patch

The fix routes the poller through the same SSRF guard as the initial load, with the

same policy, so both paths share one DNS resolution + connection pinning and cannot

diverge:

  • OpenApiSpecPoller.doFetch() now calls `safeFetch(this.url, { headers, timeoutMs,

followRedirects, ssrf }) from mcp-from-openapi instead of the global fetch()`.

  • OpenapiAdapter.startPolling() injects the adapter's resolved policy into t

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is high, an attacker needs no privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality high, integrity none, availability none.

Weakness class

GHSA-8q49-2h5h-434x is classified as CWE-918: Server-Side Request Forgery (SSRF). The server fetches a URL supplied by the caller, which can be pointed at internal systems it alone can reach.

Affected software

GHSA-8q49-2h5h-434x is recorded against 1 package.

  • @frontmcp/adapters

Timeline and source

Published on 24 July 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.

References

github.com (Web)
github.com (Web)
github.com (Web)
github.com (Package)
github.com (Web)

Details

Severity Unknown
CVSS Score N/A
CVSS Vector CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
CWE CWE-918
Public Exploit ✅ No
Source OSV
Published 2026-07-24
Updated 2026-08-20
Modified 2026-07-24
Fix URL N/A

Affected Packages

Software From version Fixed in
@frontmcp/adapters

Similar Threats

Free Vulnerability Check

Is your site affected by GHSA-8q49-2h5h-434x?

BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against GHSA-8q49-2h5h-434x and other known CVE records.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.

Browse related advisories

All advisoriesGitHub AdvisoryGitHub Advisory Undated