Skip to content

fix: validate region parameter to prevent SSRF request redirection#417

Merged
jariy17 merged 1 commit intomainfrom
fix/validate-region-ssrf-v2177374595
Apr 15, 2026
Merged

fix: validate region parameter to prevent SSRF request redirection#417
jariy17 merged 1 commit intomainfrom
fix/validate-region-ssrf-v2177374595

Conversation

@jariy17
Copy link
Copy Markdown
Contributor

@jariy17 jariy17 commented Apr 15, 2026

Summary

Fixes SSRF vulnerability where crafted region values (e.g., x@attacker.com:443/#) redirect SDK API calls — including SigV4-signed requests with credentials — to non-AWS hosts. Same vulnerability class as CVE-2026-22611.

Two-part fix:

1. Region validation for manual URL construction paths (endpoints.py, a2a.py, AgentCoreRuntimeClient, BrowserClient)

  • Layer 1: validate_region() with regex \A[a-z]{2}(-[a-z]+)+-\d+\Z using \Z anchor to prevent newline bypass
  • Layer 2: _validate_endpoint_url() verifies constructed URL hostname ends with .amazonaws.com
  • Custom InvalidRegionError(ValueError) for backward compatibility

2. Remove redundant endpoint_url from boto3 clients (CodeInterpreter, IdentityClient, ResourcePolicyClient, MemoryControlPlaneClient)

  • Boto3's own endpoint resolution produces identical URLs and includes built-in region validation
  • endpoint_url now only passed when env var override is explicitly set (BEDROCK_AGENTCORE_DP_ENDPOINT, BEDROCK_AGENTCORE_CP_ENDPOINT)

Files changed

File Change
_utils/endpoints.py validate_region(), _validate_endpoint_url(), InvalidRegionError
runtime/a2a.py Validate in build_runtime_url() (explicit + ARN-extracted region)
runtime/agent_core_runtime_client.py Validate in __init__()
tools/browser_client.py Validate in __init__(), remove endpoint_url from boto3 calls
tools/code_interpreter_client.py Remove endpoint_url from boto3 calls
services/identity.py Remove endpoint_url from boto3 calls
services/resource_policy.py Remove endpoint_url from boto3 calls
memory/controlplane.py Remove endpoint_url from boto3 calls
test_region_validation.py 54 new tests
test_code_interpreter_client.py Updated to remove endpoint mocks
test_browser_client.py Updated to remove endpoint mocks

Test plan

  • 54 new SSRF validation tests (valid regions, 20 malicious payloads, ARN extraction, all client constructors)
  • 296 total tests passing, 0 regressions
  • Verified boto3 resolves identical endpoints natively across us-west-2, us-east-1, eu-west-1
  • Verified boto3 rejects malicious regions with its own InvalidRegionError
  • Verified env var overrides still work when set

Ref: V2177374595

@jariy17 jariy17 requested a review from a team April 15, 2026 17:50
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 15, 2026

⚠️ Breaking Change Warning

Found 9 potential breaking change(s) in this PR:

�[1msrc/bedrock_agentcore/tools/browser_client.py�[0m:86: BrowserClient.control_plane_client: �[33mAttribute value was changed�[39m: boto3.client('bedrock-agentcore-control', region_name=region, endpoint_url=get_control_plane_endpoint(region), config=client_config) -> boto3.client('bedrock-agentcore-control', **cp_kwargs)
�[1msrc/bedrock_agentcore/tools/browser_client.py�[0m:92: BrowserClient.data_plane_client: �[33mAttribute value was changed�[39m: boto3.client('bedrock-agentcore', region_name=region, endpoint_url=get_data_plane_endpoint(region), config=client_config) -> boto3.client('bedrock-agentcore', **dp_kwargs)
�[1msrc/bedrock_agentcore/tools/code_interpreter_client.py�[0m:110: CodeInterpreter.control_plane_client: �[33mAttribute value was changed�[39m: session.client('bedrock-agentcore-control', region_name=region, endpoint_url=get_control_plane_endpoint(region), config=control_config) -> session.client('bedrock-agentcore-control', **cp_kwargs)
�[1msrc/bedrock_agentcore/tools/code_interpreter_client.py�[0m:116: CodeInterpreter.data_plane_client: �[33mAttribute value was changed�[39m: session.client('bedrock-agentcore', region_name=region, endpoint_url=get_data_plane_endpoint(region), config=data_config) -> session.client('bedrock-agentcore', **dp_kwargs)
�[1msrc/bedrock_agentcore/memory/controlplane.py�[0m:42: MemoryControlPlaneClient.endpoint: �[33mAttribute value was changed�[39m: os.getenv('BEDROCK_AGENTCORE_CONTROL_ENDPOINT', f'https://bedrock-agentcore-control.{region_name}.amazonaws.com') -> self.client.meta.endpoint_url
�[1msrc/bedrock_agentcore/memory/controlplane.py�[0m:41: MemoryControlPlaneClient.client: �[33mAttribute value was changed�[39m: boto3.client(service_name, region_name=self.region_name, endpoint_url=self.endpoint) -> boto3.client(service_name, **cp_kwargs)
�[1msrc/bedrock_agentcore/services/resource_policy.py�[0m:25: ResourcePolicyClient.client: �[33mAttribute value was changed�[39m: boto3.client('bedrock-agentcore-control', region_name=region, endpoint_url=get_control_plane_endpoint(region)) -> boto3.client('bedrock-agentcore-control', **cp_kwargs)
�[1msrc/bedrock_agentcore/services/identity.py�[0m:81: IdentityClient.cp_client: �[33mAttribute value was changed�[39m: boto3.client('bedrock-agentcore-control', region_name=region, endpoint_url=get_control_plane_endpoint(region)) -> boto3.client('bedrock-agentcore-control', **cp_kwargs)
�[1msrc/bedrock_agentcore/services/identity.py�[0m:85: IdentityClient.dp_client: �[33mAttribute value was changed�[39m: boto3.client('bedrock-agentcore', region_name=region, endpoint_url=get_data_plane_endpoint(region)) -> boto3.client('bedrock-agentcore', **dp_kwargs)


Note: This is an automated static analysis check. Some flagged changes may be intentional.
Please confirm each item is expected and, if so, add a migration note to CHANGELOG.md.

@jariy17 jariy17 force-pushed the fix/validate-region-ssrf-v2177374595 branch from f0e514f to c388719 Compare April 15, 2026 18:53
@jariy17 jariy17 force-pushed the fix/validate-region-ssrf-v2177374595 branch from c388719 to 0aa64b2 Compare April 15, 2026 19:16
@jariy17
Copy link
Copy Markdown
Contributor Author

jariy17 commented Apr 15, 2026

Re: Breaking Change Warning — all 9 flagged items reviewed:

#1-4, #6-9 (attribute value changed): False positives. The **cp_kwargs / **dp_kwargs pattern passes identical arguments to boto3.client() — same service, same region. The resolved endpoint URL is identical (verified across us-west-2, us-east-1, eu-west-1). No runtime behavior change.

#5 (MemoryControlPlaneClient.endpoint removed): Fixed — self.endpoint is now restored via self.client.meta.endpoint_url so existing code that reads client.endpoint continues to work.

No breaking changes in this PR.

@jariy17 jariy17 force-pushed the fix/validate-region-ssrf-v2177374595 branch from 0aa64b2 to 24c32ac Compare April 15, 2026 19:21
Comment thread src/bedrock_agentcore/_utils/endpoints.py Outdated
The region parameter was interpolated directly into endpoint URL
f-strings without validation, allowing crafted values like
"x@attacker.com:443/#" to redirect SDK API calls — including
SigV4-signed requests with credentials — to non-AWS hosts.
Same vulnerability class as CVE-2026-22611.

Defense-in-depth fix:

1. validate_region() in endpoints.py checks against regex
   \A[a-z]{2}(-[a-z]+)+-\d+\Z using \Z anchor to prevent newline
   bypass. Applied in get_data_plane_endpoint(), build_runtime_url(),
   AgentCoreRuntimeClient, and BrowserClient.

2. _validate_endpoint_url() verifies constructed URL hostname ends
   with .amazonaws.com. Also validates env var endpoint overrides.

3. Boto3-based clients (CodeInterpreter, IdentityClient,
   ResourcePolicyClient, MemoryControlPlaneClient) no longer pass
   redundant endpoint_url — boto3 resolves identical endpoints
   natively and includes its own region validation.

Ref: V2177374595
@jariy17 jariy17 force-pushed the fix/validate-region-ssrf-v2177374595 branch from 9355d4f to 20227b2 Compare April 15, 2026 19:48
Comment thread src/bedrock_agentcore/memory/controlplane.py
@jariy17 jariy17 merged commit 640b3ad into main Apr 15, 2026
36 checks passed
@jariy17 jariy17 deleted the fix/validate-region-ssrf-v2177374595 branch April 15, 2026 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants