Skip to content

fix: verify aws region - #3412

Merged
opieter-aws merged 2 commits into
strands-agents:mainfrom
opieter-aws:opieter-aws/semarang
Jul 22, 2026
Merged

opieter-aws merged 2 commits into
strands-agents:mainfrom
opieter-aws:opieter-aws/semarang

Conversation

@opieter-aws

@opieter-aws opieter-aws commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

Description

The region is interpolated straight into https://bedrock-mantle.{region}.api.aws/... with no validation. Because the sibling code mints a fresh AWS bearer token and attaches it as the request's auth header, a region like x@attacker.com:443/# re-points the host to attacker.com and ships a live credential there on the first request.

Was already fixed this for Nova Sonic (#2990) but not propagated it to the Mantle path. This centralizes that validation as a shared validate_region helper, applies it at each SDK's region-resolution chokepoint (so config-, session-, and env-sourced regions are all covered), and refactors Nova Sonic to reuse it so the two paths can't drift again.

Two constraints worth flagging for review:

  • Python uses \A...\Z, not ^...$ — Python's $ matches before a trailing newline, so ^...$ would let us-east-1\n through under .match()/.search(). \A...\Z is fully self-anchored regardless of which method a future caller uses. The TS literal keeps /^...$/ (JS has no \A\Z, and JS $ without the m flag is already end-of-string).
  • [0-9] rather than \d — Python's \d also matches Unicode digits (us-east-١ would pass), so the two SDKs' patterns are now byte-identical ASCII, honoring the cross-SDK parity requirement.

Related Issues

Prior art: #2990

Documentation PR

No documentation changes — internal validation hardening with no public API surface change.

Type of Change

Bug fix

Testing

Ran the Python model suites (test__validation, test_openai, test_openai_responses) and the Nova Sonic region tests under the bidi extras, plus the TypeScript Mantle suite — together these cover the config, boto3-session, and env-var resolution paths in both SDKs, valid regions (including us-gov-east-1), and the malformed/Unicode/newline rejection cases. Also drove both SDKs end-to-end against the real public API (OpenAIModel(bedrock_mantle_config=...) / resolveMantleRegion) with the report's x@attacker.com:443/# payload and confirmed it is rejected before any token is minted, while a legitimate region still builds the correct URL.

  • I ran hatch run prepare

Checklist

  • I have read the CONTRIBUTING document
  • I have reviewed and understand every line of code in this PR, including any generated by AI tools, and I can explain why it works
  • My change is focused and reasonably small; I have split unrelated work into separate PRs
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@github-actions github-actions Bot added size/m bug Something isn't working area-community Related to community and contributor health labels Jul 22, 2026
@opieter-aws

Copy link
Copy Markdown
Contributor Author

@strandly-the-agent review

@opieter-aws
opieter-aws marked this pull request as ready for review July 22, 2026 16:34
@opieter-aws
opieter-aws requested a review from a team as a code owner July 22, 2026 16:34
@opieter-aws
opieter-aws requested a review from liramon2 July 22, 2026 16:34
@github-actions

Copy link
Copy Markdown
Contributor

Assessment: Approve

Clean, well-scoped security fix. The shared validate_region helper is applied at every region-resolution chokepoint (config, boto3 session, env/default) across both the Mantle and Nova Sonic paths, and the region flows unchanged into URL construction — so a malformed region can no longer re-point a signed request. I ran both the Python (\A...\Z) and TS (^...$) patterns against the attack payloads and they reject x@attacker.com:443/#, trailing/leading newlines, uppercase, missing suffixes, and non-ASCII digits/letters identically. Verified there are no other spots interpolating a region into the endpoint URL.

Review notes
  • Security: Allowlist regex (only [a-z], -, [0-9]) structurally excludes URL control chars; no ReDoS risk since the - delimiters make (-[a-z]+)+ unambiguous. ✅
  • Cross-SDK parity: The \A\Z vs ^$ divergence and [0-9] vs \d choice are correct and well-documented in the code comments. ✅
  • API surface: Internal only (_validation.py module / TS @internal, not exported) — no API review needed, consistent with the PR description. ✅
  • Behavior change: Nova Sonic is now stricter than before (anchored + ASCII-only digits), which is the intended hardening; no real AWS region is affected. ✅
  • Tests: Parametrized and cover the key rejection cases in both SDKs. One minor convention gap noted inline (linking the tracking issue).

Nicely done — refactoring the two paths onto one helper closes the drift that let this gap exist.

@strandly-the-agent strandly-the-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR: Approve — at 43a3af6967e5a8e4ad959d93f7289f50e1e92bf4, every region-to-URL path is validated before token or client setup; no actionable findings.

✅ Python focused suites: 242 passed
✅ TypeScript Mantle suite: 31 passed, no type errors
✅ Cold Python/Node probes rejected prefix/control/newline/NUL/Unicode/100k inputs; the unvalidated report payload resolves to attacker.com
✅ git diff --check; exact-head GitHub CI completed green
⚠️ Current CI rerun is still finishing; local Nova suite setup was blocked by missing portaudio.h

Review breakdown
  • Correctness/security: All three manual region-interpolated URL sinks are covered. Python Mantle validates explicit, attached-session, and default-session regions; TypeScript validates explicit and environment regions; Nova validates before endpoint/SigV4 setup.
  • Regex semantics: Both SDKs use full-string ASCII allowlists. Direct probes confirmed the shipped patterns reject URL delimiters, prefix/suffix payloads, line terminators, NUL, Unicode digits, and oversized input.
  • API/compatibility: Helpers remain private/internal and package exports are unchanged; no API-review label is needed.
  • Tests: Existing coverage proves the security behavior. A few possible mutation-hardening additions did not reveal a product defect, so I left them as non-blocking rather than add review noise.
  • Pass caveat: The advanced adversarial model was unavailable and two default retries returned empty, so I independently ran the cold security probes above.

@opieter-aws
opieter-aws merged commit 81bccd8 into strands-agents:main Jul 22, 2026
77 of 80 checks passed
@opieter-aws
opieter-aws deleted the opieter-aws/semarang branch July 22, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-community Related to community and contributor health bug Something isn't working size/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants