aws / aws/agent-toolkit-for-aws

aws-core: secret-safety hook does not block GetSecretValue issued through aws___run_script (the path asm-exec uses)

Open
#307 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
2.6k
Forks
306
Avg merge
1d 1h
Merged PRs (30d)
51

Description

**Component:** `plugins/aws-core/com.anthropic.claude-code/hooks/secret-safety.py`

## Summary

The aws-core PreToolUse hook is documented as blocking `GetSecretValue` "via MCP tools or structured AWS API calls". It does block the AWS CLI shape, inline SDK method calls, and the localhost:2773 daemon URL. It does not block the one MCP shape that actually fetches secrets on the current server: a `run_script` body that calls `call_boto3(service_name="secretsmanager", operation_name="GetSecretValue", ...)`. Since `aws___call_aws` was removed and `asm-exec` moved to `run_script` (#296), this is the primary programmatic path to a secret value, and it passes the hook unchanged.

## Reproduction

Pipe this PreToolUse payload into the hook exactly as `hooks.json` invokes it:

```json
{"tool_name": "mcp__aws-mcp__aws___run_script",
"tool_input": {"code": "result = await call_boto3(service_name=\"secretsmanager\", operation_name=\"GetSecretValue\", params={\"SecretId\": \"x\"})\nresult"}}
```

Expected: a deny decision. Observed: empty stdout, exit 0 (allowed). The same payload with `operation_name="get-secret-value"` or `"BatchGetSecretValue"` is also allowed. For comparison, the Bash payload `aws secretsmanager get-secret-value --secret-id x` is correctly denied.

Reproduced 2026-09-09 on Windows 11 with Python 3.14, aws-core 1.1.0 as pinned by `claude-plugins-official` (toolkit commit 08ad220e). The hook file at `main` (df5d2e84) is byte-identical, so the gap is present upstream too.

## Root cause

Two independent problems in `secret-safety.py`:

1. **Unreachable `run_script` branch.** `main()` first tests `tool_name.startswith("mcp__")` and that branch always terminates with `allow()` (a `sys.exit`). Every MCP tool name starts with `mcp__`, so the later `if "run_script" in tool_name:` branch can never execute for an MCP tool. It is effectively dead code.

2. **Operation detection needs a call parenthesis.** Even within the `mcp__` branch, the structured check reads `service_name` / `operation_name` from the top level of `tool_input`, which `run_script` does not have (it has `code`). The fallback `SDK_CALL_PATTERN` requires `get_secret_value(`, `GetSecretValueCommand(`, or `GetSecretValue(Request|Command)?(`. The boto3-kwargs form used by `call_boto3` is `operation_name="GetSecretValue", params=`, which has no parenthesis after the operation name and so never matches. `CLI_GSV_PATTERN` does not apply either because there is no `aws secretsmanager` prefix.

## Suggested fix

- Move the `run_script` check ahead of, or fold it into, the `mcp__` branch so it runs for `mcp__*run_script*` tool names.
- Detect the operation independent of call syntax. A conservative rule that covers boto3 kwargs, the CLI string, SDK method calls, and JS command classes without false positives: normalize each string in `tool_input` (lowercase, strip `-` and `_`) and deny when it contains both `getsecretvalue` and `secretsmanager`. Requiring both tokens avoids denying a script that merely mentions the operation name for another service.
- Add these payloads to the hook's tests: `run_script` with `operation_name="GetSecretValue"`, with `"get-secret-value"`, with `"BatchGetSecretValue"`, and a `DescribeSecret` control that must stay allowed.

A minimal user-level supplementary hook implementing the normalized-token rule has been running on my side since 2026-09-09 and passes those cases; happy to turn it into a PR against `secret-safety.py` if the approach is acceptable.

## Related, out of scope here

The `claude-plugins-official` marketplace still pins aws-core at 08ad220e (2026-09-03), which ships the pre-#296 `asm-exec` calling the removed `aws___call_aws`. On that build every `{{resolve:...}}` fails silently with "Failed to resolve" (the server answers `-32600 The call_aws tool has been removed`). That is a marketplace-pin lag rather than a toolkit bug, but users installing today get a non-working `asm-exec` alongside this hook gap.

Contributor guide

Open the contributing guide

Research direction

Start with plugins/aws-core/com.anthropic.claude-code/hooks/secret-safety.py and reproduce the provided mcp__aws-mcp__aws___run_script payload through the hook as hooks.json invokes it. Trace the mcp__ and run_script handling, then add the listed run_script cases and the DescribeSecret control to the hook's tests. Done means secret-fetching run_script payloads are denied while the control remains allowed, alongside the existing AWS CLI behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, python
Domain
security, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.