FlawOpen

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

● CVE-2026-106032 · CVSS v4 5.7 · 보통
보안 연구 · FlawOpen

CVE-2026-106032: AgentCore OpenAPI 가져오기 도구 SSRF

Starter Toolkit 0.3.13 이하 버전은 에이전트 가져오기 중 외부 OpenAPI 참조를 해석했습니다. 변조된 액션 그룹 데이터로 인해 외부 요청이나 로컬 파일 읽기가 발생할 수 있었습니다. 0.3.14 이상으로 업그레이드하고 영향을 받은 에이전트를 다시 가져온 뒤 생성된 아티팩트를 교체하세요.[1], [2], [3]

💡 알기 쉬운 설명 (ELI5)

가져오기 도구를 문서의 참조를 따라 서류철을 만드는 직원이라고 생각해 보세요. 취약한 직원은 서류철 바깥이나 로컬 파일을 가리키는 참조도 따라갔습니다. 그래서 신뢰해 보이는 에이전트가 정리 중인 컴퓨터에서 데이터를 가져오거나 읽게 할 수 있었습니다. 수정 버전은 같은 문서 안의 참조만 허용합니다.[2], [7], [8]

핵심 개념 및 용어

OpenAPI $ref
OpenAPI 스키마나 정의를 가리키는 참조입니다. 프래그먼트는 현재 문서 안을 가리키고 외부 참조는 다른 리소스를 가리킬 수 있습니다.[1]
Prance ResolvingParser
Starter Toolkit이 에이전트 가져오기 중 OpenAPI 참조를 로드하고 해석하는 파서입니다.[2]
SSRF
Server-side request forgery: 신뢰할 수 없는 입력이 소프트웨어 자신의 네트워크 위치에서 요청을 보내게 합니다.[7], [8]
CWE-918
CVE 레코드의 구조화된 기본 cweId는 CWE-918(Server-Side Request Forgery)입니다. 설명에는 파일 경로의 외부 제어 측면을 나타내는 CWE-73도 명시되어 있습니다.[2], [3], [5]
CWE-73: External Control of File Name or Path
같은 CVE 레코드는 로컬 파일 읽기 측면에 대해 CWE-73(파일 이름 또는 경로의 외부 제어)도 명시합니다. CWE-73은 문제 유형 설명에 있고, 구조화된 기본 cweId는 CWE-918입니다.[3], [9]

프레임워크 매핑

근본 원인 분석 (Root Cause)

0.3.13에서 get_agent_info()는 액션 그룹의 OpenAPI 페이로드를 prance.ResolvingParser에 직접 전달했고 참조 해석 유형을 제한하지 않았습니다. 0.3.14에서는 파서 실행 전에 assert_local_references_only()를 호출합니다. 이 재귀 검사는 내부 프래그먼트 접두사 #/로 시작하지 않는 문자열 $ref를 거부하고, 이후 resolve_types=RESOLVE_INTERNAL을 설정합니다. 이로써 해당 가져오기 경로에서 파서가 외부 OpenAPI 참조를 가져오지 못하게 합니다. 유지관리자 테스트는 파서 호출 전 거부를 확인하고 HTTP, file, 절대 경로, 네트워크 경로 참조를 검사하며 문서 내부 프래그먼트는 허용합니다. 이 결과를 다른 가져오기 경로로 확대하거나 프로세스의 모든 네트워크 및 파일 접근을 차단한다고 주장하지 마세요. 지원되는 해결책은 업그레이드입니다. 코드 비교는 업스트림 경계를 보여 주며 악용 절차가 아닙니다. GitHub 보안 권고는 @seankohjs를 제보자로 명시하며, AWS는 취약점의 조정된 공개에 협력한 Koh Jun Sheng에게 감사의 뜻을 전합니다.[2], [7], [8], [1]

단계별 공격 실행 흐름

단계 1

같은 계정의 주체가 에이전트 데이터를 변경

같은 AWS 계정의 인증된 principal은 Bedrock Agent 작업 그룹의 OpenAPI 스키마를 수정해 특수하게 구성된 외부 참조 값을 넣을 수 있어야 합니다. 인증 없이 인터넷에서 바로 수행되는 공격은 아닙니다.[2]

단계 2

다른 사용자가 에이전트를 가져옴

사용자가 영향을 받는 Starter Toolkit 가져오기 흐름을 실행합니다. 취약 버전은 이 작업 중 액션 그룹 OpenAPI를 처리합니다.[1], [2]

단계 3

파서가 외부 참조를 해석

0.3.13은 내부 참조로 제한하지 않은 채 문서를 ResolvingParser에 전달했습니다. 조작된 외부 참조가 가져오기 환경에서 외부 요청이나 로컬 파일 접근을 일으킬 수 있었습니다.[7], [2]

단계 4

업그레이드하고 재가져온 뒤 아티팩트 교체

0.3.14 이상으로 업그레이드하고 취약 버전으로 가져온 에이전트를 다시 가져온 뒤 로컬 및 배포된 아티팩트를 교체하세요. 가능하면 더 이상 지원되지 않는 Starter Toolkit에서 @aws/agentcore로 마이그레이션하세요.[1], [8]

소스 코드 비교: 취약한 구현 vs 보안 패치

이 발췌는 공식 0.3.13 및 0.3.14 소스 배포본에서 가져왔습니다. 수정은 Prance 실행 전에 외부 $ref를 거부하고 resolver를 내부 참조로 제한합니다. 업스트림 테스트는 파서 전 거부와 내부 프래그먼트 허용을 확인합니다. 이는 범위가 한정된 소스 비교이며 요청 예제가 아닙니다. 발췌를 복사하지 말고 패키지를 업그레이드하세요.[7], [8], [2]

소스 코드 발췌: AgentCore 가져오기 도구 0.3.13 및 0.3.14 소스 발췌

취약한 구현
# 0.3.13: 파서가 OpenAPI 문서의 참조를 해석합니다.
parser = ResolvingParser(
    spec_string=json.dumps(action_group["apiSchema"]["payload"])
)
action_group["apiSchema"]["payload"] = parser.specification
보안 강화 패치
# 0.3.14: 파싱 전에 외부 참조를 거부합니다.
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}]")

엔지니어링 및 시스템 보안 강화 체크리스트

출처