Skip to main content

3-layer safety model & IAM guardrails

Running AI agents against cloud accounts requires defense in depth. Every plugin in the TalkOps DevOps Plugins Marketplace—across all 17 Agent Plugins and all 21 Vertical Plugins—enforces a three-layer safety architecture designed to prevent accidental credential exposure, unauthorized mutations, and runaway query costs.

LayerEnforcement PointWhat It ProtectsWhat Can Bypass It
1. Server FlagsMCP Server Startup (.mcp.json / mcp.json)Drops mutating MCP tools on every host via --read-only, --readonly, ALLOW_WRITE=false, and READ_OPERATIONS_ONLY=trueDirect shell commands (aws ..., terraform ...)
2. Deterministic HooksPreToolUse / PostToolUse (hooks/hooks.json)Intercepts both shell (Bash) and AWS MCP tool calls to block secret exfiltration and gate mutating CLI/IaC commandsHosts that do not execute hooks or TALKOPS_AWS_MUTATION_GATE=off
3. AWS IAMAWS Account & Organizations Control PlaneEnforces cryptographic permission boundaries on every API call from any tool or shellNothing — IAM is the ultimate boundary
Configure IAM as if Layers 1 and 2 did not exist

Layers 1 and 2 prevent accidents and enforce interactive confirmation workflows, but AWS IAM is the only boundary an agent cannot bypass. Always pair agents with least-privilege IAM roles.


Layer 1: Server-side read-only defaults​

  1. awslabs MCP servers default to read-only: Bundled awslabs servers omit --allow-write and --allow-sensitive-data-access by default, preventing unapproved mutations or secret reads at the MCP server layer across all hosts.
  2. Dedicated read-only specialist agents: Advisory and diagnostic specialists—aws-sre-agent, aws-finops-engineer, and aws-solutions-architect—are marked aws_read_only: true and launch the managed AWS MCP proxy (aws-mcp) with --read-only, which strips aws___call_aws, aws___run_script, and aws___get_presigned_url non-read operations before the model ever sees the tool list.

Layer 2: Deterministic PreToolUse & PostToolUse hooks​

Every AWS agent plugin and vertical plugin ships stdlib-only Python safety hooks executed via a portable interpreter chain (python3 → python → py -3):

1. secret-safety.py (PreToolUse)​

Inspects shell commands (Bash) and AWS MCP calls before execution and blocks any attempt to:

  • Print, dump, exfiltrate, or echo AWS secret access keys, session tokens, .aws/credentials, or private keys.
  • Call secret-retrieval APIs (secretsmanager:GetSecretValue, ssm:GetParameter with decryption) without explicit authorization.
  • Hardcode credentials inside files or CLI flags.

2. aws-mutation-gate.py (PreToolUse)​

Intercepts mutating CLI and MCP operations across 11 infrastructure toolchains:

  • aws CLI mutating subcommands
  • terraform / tofu (apply, destroy, import, state rm, state mv)
  • cdk (deploy, destroy, bootstrap)
  • sam (deploy, delete)
  • pulumi (up, destroy, refresh)
  • eksctl, kubectl, helm, copilot, and amplify

How aws-mutation-gate.py decides:

  • For read-only agents (aws-sre-agent, aws-finops-engineer, aws-solutions-architect), mutating operations are denied outright.
  • For write-capable agents and vertical plugins, mutating operations require explicit human confirmation (permissionDecision: "ask" in Claude Code / TalkOps).
  • Override behavior when needed via the TALKOPS_AWS_MUTATION_GATE environment variable:
# Modes: off | warn | ask (default) | deny
export TALKOPS_AWS_MUTATION_GATE=deny

3. Domain-specific hooks​

  • session-aws-preflight.py: Verifies AWS credential validity, STS caller identity, and target region at session start (aws-essentials).
  • iac-post-write-lint.py (PostToolUse): Automatically runs cfn-lint, cfn-guard, and terraform validate immediately after the agent edits CloudFormation, CDK, or Terraform files (aws-iac-engineer, aws-infrastructure-as-code).
  • finops-sql-and-cost-gate.py (PreToolUse): Validates Athena Cost and Usage Report (CUR 2.0 / FOCUS) SQL queries to ensure partition filters (billing_period, year, month) are present before scanning S3 data (aws-finops-engineer, aws-cost-optimization).
  • Aurora DSQL transaction checks (PostToolUse): Verifies optimistic concurrency and transaction state after DSQL schema operations.

Layer 3: AWS IAM guardrails & MCP condition keys​

1. Give read-only agents read-only IAM credentials​

Run aws-sre-agent, aws-finops-engineer, and aws-solutions-architect with an AWS profile backed by ReadOnlyAccess (or ViewOnlyAccess + AWSBillingReadOnlyAccess), and attach an explicit Deny statement for secret material (ReadOnlyAccess otherwise allows secretsmanager:GetSecretValue, ssm:GetParameter*, and s3:GetObject):

iam-deny-secret-material.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenySecretMaterial",
"Effect": "Deny",
"Action": [
"secretsmanager:GetSecretValue",
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath",
"kms:Decrypt",
"support:CreateCase",
"support:AddCommunicationToCase"
],
"Resource": "*"
}
]
}

2. Give write-capable agents scoped deployment roles​

Never run IaC, platform, serverless, deployment, or database agents with AdministratorAccess:

  • AWS CDK: Allow the agent's role only cloudformation:* on its target stacks plus sts:AssumeRole on the CDK bootstrap execution roles.
  • Terraform / OpenTofu: Separate the plan role (read-only + S3 state read + DynamoDB/S3 lock write) from the apply role. Have the agent generate and validate the plan with the plan role, and switch profiles only after reviewing the saved plan.
  • State protection: Restrict s3:PutObject and s3:DeleteObject on the Terraform state bucket to the apply role and enable S3 Versioning + Object Lock.

3. Restrict the managed AWS MCP server with IAM condition keys​

Requests forwarded through the managed AWS MCP server (aws-mcp) carry two cryptographic IAM condition keys that the caller cannot spoof:

  • aws:ViaAWSMCPService (Bool): true for any request forwarded by an AWS-managed MCP server.
  • aws:CalledViaAWSMCP (String): The service principal of the forwarding MCP server (for example, aws-mcp.amazonaws.com).

Attach this policy to block high-risk write actions coming through MCP while still permitting read-only discovery:

iam-deny-high-risk-writes-via-mcp.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyHighRiskWritesViaMCP",
"Effect": "Deny",
"Action": [
"iam:*",
"organizations:*",
"ec2:Delete*", "ec2:Terminate*", "ec2:Modify*", "ec2:Authorize*", "ec2:Revoke*",
"s3:Delete*", "s3:PutBucketPolicy", "s3:PutBucketAcl", "s3:PutPublicAccessBlock",
"rds:Delete*", "rds:Modify*",
"dynamodb:DeleteTable", "dynamodb:UpdateTable",
"cloudformation:CreateStack", "cloudformation:UpdateStack", "cloudformation:DeleteStack",
"cloudformation:ExecuteChangeSet",
"lambda:Delete*", "lambda:Update*", "lambda:AddPermission",
"kms:ScheduleKeyDeletion", "kms:DisableKey", "kms:PutKeyPolicy"
],
"Resource": "*",
"Condition": {
"Bool": {
"aws:ViaAWSMCPService": "true"
}
}
}
]
}
MCP path vs. shell path

The aws:ViaAWSMCPService and aws:CalledViaAWSMCP condition keys apply only to requests routed through the managed AWS MCP server. When an agent runs aws ... or terraform apply in its shell, those requests use the role's standard permissions—so always combine MCP condition keys with scoped role permissions.

4. CloudTrail attribution per agent​

Configure a distinct role_session_name per specialist agent in ~/.aws/config (for example, role_session_name = talkops-aws-iac-engineer or role_session_name = talkops-aws-sre-agent) so AWS CloudTrail logs clearly attribute every API call to the exact agent that executed it.