Repository navigation
Conversation
The Strands plugin and LangGraph tools exposed user_id as an LLM-controllable tool argument whose value won over the configured identity. A prompt-injected agent could supply a different user_id to attempt an identity override. The managed service already scopes every read to the server-resolved identity, so no tenant boundary was crossed, but the SDK should not let the model attempt the override in the first place. Add resolve_authoritative_user_id() in config.py and route all 8 tool sites (4 Strands + 4 LangGraph) through it: the configured identity is authoritative, a differing tool-supplied value is ignored and logged. Tool signatures are unchanged (no schema break). Adds regression tests and updates the prior precedence tests to assert the hardened behavior.
…gGraph) The LangGraph middleware's lenient fallback infers an x402 payment challenge from raw tool content that lacks the trusted PAYMENT_REQUIRED: marker, so any tool's output could mint a signed authorization to an actor-chosen recipient and amount (CWE-863: improper authorization on an untrusted channel). The Strands plugin is marker-only and unaffected. Add two defense-in-depth controls on AgentCorePaymentsPluginConfig: - allow_unmarked_402_detection (default True, preserves current behavior): when False, both _fallback_detect_402 call sites are skipped so only the trusted marker path derives a payment. - pre_sign_policy callback at the single signing chokepoint (_generate_payment_header), invoked on every detection path before any value moves; fail-closed on a falsy return or a raise. Adds regression tests plus an end-to-end exploit-reproduction suite that drives the full wrap_tool_call path with an attacker-controlled unmarked payload and asserts no authorization is minted once either control is active.
|
Claude Security Review: no high-confidence findings. (run) |
|
RequestError [HttpError]: Resource not accessible by integration Looks like I lack perms.. @aidandaly24 I wonder if you can grant them to me! Thank you. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #705 +/- ##
=======================================
Coverage ? 89.62%
=======================================
Files ? 124
Lines ? 10921
Branches ? 1713
=======================================
Hits ? 9788
Misses ? 744
Partials ? 389
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
#706 -- retrying with permissions |
Issue #, if available: N/A
Description of changes:
This PR adds two defense-in-depth hardening controls to the AgentCore Payments
integrations (Strands plugin and LangGraph middleware). Both are backward
compatible: no tool schema changes, and the content-inferred 402 default is
preserved so existing integrations behave exactly as before unless they opt in.
1. Make the configured
user_idauthoritative in agent toolsThe Strands plugin and LangGraph tools exposed
user_idas an LLM-controllabletool argument whose value won over the configured identity. A prompt-injected
agent could supply a different
user_idto attempt an identity override. Themanaged service already scopes every read to the server-resolved identity, so
no tenant boundary was crossed — but the SDK should not let the model attempt
the override in the first place.
resolve_authoritative_user_id()helper inpayments/integrations/config.py. When an identity is configured, it isauthoritative and a differing tool-supplied
user_idis ignored and logged.When no identity is configured (bearer/JWT auth, where the server resolves the
user from the token), the requested value passes through unchanged.
2. Gate content-inferred 402 detection and add a pre-sign policy (LangGraph)
The LangGraph middleware's lenient fallback infers an x402 payment challenge
from raw tool content that lacks the trusted
PAYMENT_REQUIRED:marker, so anytool's output could cause a signed authorization to be minted for a recipient
and amount taken from untrusted content (CWE-863, improper authorization on an
untrusted channel). The Strands plugin is marker-only and is unaffected.
Two new, opt-in controls on
AgentCorePaymentsPluginConfig:allow_unmarked_402_detection: bool = True(default preserves currentbehavior). When
False, both_fallback_detect_402call sites are skipped,so a payment is derived only from the integration's own payment-bearing tools
via the trusted marker.
pre_sign_policy: Optional[Callable[[Any], bool]] = None. A callback invokedat the single signing chokepoint (
_generate_payment_header) on everydetection path (marked, unmarked, and error-retry) before any value moves. It
receives the payment-required request (carrying
payToand amount) andreturns
Trueto allow orFalseto block. It is fail-closed: a falsy returnor a raised exception blocks signing. Integrators can use it to enforce a
recipient/amount allowlist regardless of the detection default.
Tests
pre-sign policy (allow/block/fail-closed).
wrap_tool_callpath with an attacker-controlled, unmarked payload naming anattacker-chosen
payTo/amount. It asserts (a) the permissive default wouldsign to the attacker (pinning the attack surface) and (b) no authorization is
minted once either control is active, while a legitimate allowlisted recipient
still signs.
user_idoverride-wins precedence areupdated to assert the hardened behavior.
Full payments test suite: 940 passed, 9 skipped.
ruff checkclean.By submitting this pull request, I confirm that you can use, modify, copy, and
redistribute this contribution, under the terms of your choice.