FlawOpen

flawopen.com/Teardowns/cve-2026-106032-bedrock-agentcore-openapi-reference-ssrf

● CVE-2026-106032 · CVSS v4 5.7 · Medium
FlawOpen Security Research

CVE-2026-106032: AgentCore Importer OpenAPI SSRF

Bedrock AgentCore Starter Toolkit versions through 0.3.13 resolved external OpenAPI references while importing an agent, allowing crafted action-group data to trigger outbound requests or local-file reads. Upgrade to 0.3.14 or later, re-import affected agents, and replace generated artifacts.[1], [2], [3]

💡 Plain English Explainer (ELI5)

An agent importer is like a clerk assembling a binder from pages listed in a specification. The vulnerable clerk followed any reference written on a page, including directions outside the binder or into local files. A trusted-looking agent could therefore make the importing workstation fetch or read material while assembling it. The fix limits references to pages already inside that same document.[2], [5], [6]

Core Concepts & Subsystem Terms

OpenAPI $ref
A pointer in an OpenAPI document to a schema or other definition. A fragment-only pointer refers within the current document; an external pointer can name another resource.[1]
Prance ResolvingParser
The parser the Starter Toolkit uses to load and resolve OpenAPI references during agent import.[2]
SSRF
Server-side request forgery: untrusted input causes software to make a request from its own network position.[5], [6]
CWE-918
The CVE record's structured primary cweId is CWE-918 (Server-Side Request Forgery). Its description also names CWE-73 for the externally controlled file-path aspect.[2], [3], [7]
CWE-73: External Control of File Name or Path
The same CVE record names CWE-73, External Control of File Name or Path, for the local-file-read aspect. CWE-73 appears in the record's problem-type description; CWE-918 is its structured primary cweId.[3], [9]

Framework mappings

Root Cause Analysis

In 0.3.13, get_agent_info() loaded an action group's OpenAPI payload and passed its JSON serialization directly to prance.ResolvingParser. The parser resolved references without a restrictive resolve_types setting. In 0.3.14, the importer first calls assert_local_references_only(), which recursively rejects string $ref values that do not start with the in-document fragment prefix #/, then constructs ResolvingParser with resolve_types=RESOLVE_INTERNAL. This prevents the parser from fetching external OpenAPI references through this import path. The maintainer tests assert rejection happens before parser invocation and cover HTTP, file, absolute-path, and network-path references, while allowing a fragment-only local pointer. Do not extend this finding to unrelated importer code or claim it blocks all network or file access in the process. The supported fix is upgrading; the code comparison isolates the upstream boundary and is not an exploit recipe. The GitHub advisory lists @seankohjs as the reporter; AWS credits Koh Jun Sheng for collaborating through coordinated vulnerability disclosure.[2], [5], [6], [1]

Step-by-Step Attack Flow

Step 1

A same-account principal changes agent data

An authenticated principal in the same AWS account must be able to modify the Bedrock Agent action group's OpenAPI schema to place a crafted external-reference value there. This is not an unauthenticated internet attack.[2]

Step 2

Another user imports the agent

A user runs the affected Starter Toolkit import workflow. The vulnerable versions parse the action-group OpenAPI payload as part of this operation.[1], [2]

Step 3

The parser resolves a non-local reference

Version 0.3.13 passed the document directly to ResolvingParser without restricting resolution to internal references. A crafted external reference could cause outbound requests or local-file access from the import environment.[5], [2]

Step 4

Upgrade, re-import, and replace artifacts

Upgrade to 0.3.14 or later, re-import agents that were imported with affected versions, and replace both local and deployed generated artifacts. Migrate from the deprecated Starter Toolkit to @aws/agentcore when feasible.[1], [6]

Source Code: Flaw vs. Secure Implementation

These excerpts come from the published 0.3.13 and 0.3.14 source distributions. The fix rejects non-fragment $ref strings before Prance runs and also restricts resolver types to internal references. Upstream tests verify that external HTTP, file, absolute-path, and network-path references are rejected before parser invocation, while in-document fragments remain accepted. This is a focused source comparison, not a request example; upgrade rather than copying excerpts into an application.[5], [6], [2]

Source excerpt: bedrock_agentcore_starter_toolkit/cli/create/import_agent/agent_info.py and services/import_agent/utils.py — focused upstream excerpts

UNPATCHED FLAW
# 0.3.13: the parser resolves references from the supplied OpenAPI document.
parser = ResolvingParser(
    spec_string=json.dumps(action_group["apiSchema"]["payload"])
)
action_group["apiSchema"]["payload"] = parser.specification
HARDENED SECURE PATCH
# 0.3.14: reject external references before parsing.
assert_local_references_only(action_group["apiSchema"]["payload"])
parser = ResolvingParser(
    spec_string=json.dumps(action_group["apiSchema"]["payload"]),
    resolve_types=RESOLVE_INTERNAL,
)

def assert_local_references_only(node, path: str = "$") -> None:
    if isinstance(node, dict):
        reference = node.get("$ref")
        if isinstance(reference, str) and not reference.startswith("#/"):
            raise ValueError(
                f"External OpenAPI references are not supported: {reference!r} at {path}."
            )
        for key, child in node.items():
            assert_local_references_only(child, f"{path}.{key}")
    elif isinstance(node, list):
        for index, child in enumerate(node):
            assert_local_references_only(child, f"{path}[{index}]")

Engineering & System Hardening Checklist

Sources