Protect AWS production profiles in Claude Code with hooks
Gabriele Mariotti shows how to use Claude Code's `PreToolUse` hook to allow all AWS CLI commands by default while forcing explicit confirmation only when a command targets a protected production profile.
Score breakdown
Teams using Claude Code for AWS work can adopt this pattern to let AI agents move freely across dev and staging environments while ensuring a human is always in the loop before any production account is touched — without modifying daily workflows.
- 01A blanket `Bash(aws *)` allow rule in `settings.json` grants Claude Code permission to run any AWS CLI command without confirmation.
- 02A `PreToolUse` hook intercepts only AWS commands using a two-layer filter: `matcher: "Bash"` and `"if": "Bash(aws *)"`.
- 03The guard script `aws-prod-guard.sh` reads the pending command from stdin as JSON using `jq`.
Gabriele Mariotti outlines a problem familiar to teams using Claude Code with AWS: the two obvious permission settings are both unsatisfying. Adding `Bash(aws *)` to the allow list removes all friction but lets production commands run unconfirmed, while manually approving every AWS call is tedious even for harmless operations like `aws s3 ls` on dev buckets. The solution layers a `PreToolUse` hook on top of the broad allow rule to create a selective confirmation gate.
When a match is found, it returns `permissionDecision: "ask"` along with the profile name, description, and account ID, which Claude surfaces to the user as a confirmation prompt.
The hook configuration in `~/.claude/settings.json` uses two filters: an outer `matcher: "Bash"` to select the tool type, and an inner `"if": "Bash(aws *)"` pre-filter so the guard script is only invoked for AWS commands — not every `git`, `npm`, or `make` call. The script `aws-prod-guard.sh` reads the command from stdin via `jq`, then iterates over entries in `aws-prod-profiles.json`, checking whether the command references a protected profile via `--profile`, `AWS_PROFILE`, or `AWS_DEFAULT_PROFILE`. When a match is found, it returns `permissionDecision: "ask"` along with the profile name, description, and account ID, which Claude surfaces to the user as a confirmation prompt. If no protected profile is detected, the script exits silently and Claude proceeds normally. Protected profiles are managed in a separate JSON file, making it easy to add or remove entries without modifying the script itself.
Key facts
- 01A blanket `Bash(aws *)` allow rule in `settings.json` grants Claude Code permission to run any AWS CLI command without confirmation.
- 02A `PreToolUse` hook intercepts only AWS commands using a two-layer filter: `matcher: "Bash"` and `"if": "Bash(aws *)"`.
- 03The guard script `aws-prod-guard.sh` reads the pending command from stdin as JSON using `jq`.
- 04When a protected production profile is detected, the hook returns `permissionDecision: "ask"`, pausing Claude and prompting the user.
- 05Protected profiles are stored in a separate `aws-prod-profiles.json` file with `profile`, `account`, and `description` fields.
- 06The confirmation message shown to the user includes the profile name, description, and AWS account ID.
- 07Non-production commands exit the hook silently and proceed without any interruption.
Topics
Summary and scoring are generated automatically from the original article. We always link back to the publisher and never republish images or paywalled content. Last processed Apr 24, 2026 · 17:11 UTC. How this works →