God keys in .env for “the bot” are how you get a very polite breach. Agents need per-tool IAM roles, short-lived credentials, and Access Analyzer on any policy an agent proposes.
⚡ TL;DR: One role per tool family. STS AssumeRole with session tags (
run_id). Never embed long-lived keys in prompts. Analyze generated policies before apply.
Role per tool family
# terraform/agent_roles.tf
resource "aws_iam_role" "agent_s3_read" {
name = "agent-s3-read"
assume_role_policy = data.aws_iam_policy_document.agent_trust.json
}
resource "aws_iam_role" "agent_sandbox_apply" {
name = "agent-sandbox-apply"
assume_role_policy = data.aws_iam_policy_document.agent_trust.json
}
# creds.py
import boto3
sts = boto3.client("sts")
def session_for(tool_family: str, run_id: str):
role = ROLES[tool_family]
out = sts.assume_role(
RoleArn=role,
RoleSessionName=f"agent-{run_id}"[:64],
DurationSeconds=900,
Tags=[{"Key": "run_id", "Value": run_id}],
)
c = out["Credentials"]
return boto3.Session(
aws_access_key_id=c["AccessKeyId"],
aws_secret_access_key=c["SecretAccessKey"],
aws_session_token=c["SessionToken"],
)
Access Analyzer on generated policies
aws accessanalyzer validate-policy \
--policy-document file://proposed.json \
--policy-type IDENTITY_POLICY
❌ Applying model-written IAM JSON because “it looks least-privilege” — validate and human-review.
Closing checklist
- [ ] Per-tool roles + STS
- [ ] Session tags with run_id
- [ ] Validate policies before apply
- [ ] Short durations (≤15m)
- [ ] CloudTrail on AssumeRole
Series navigation
Day 62: SSRF and Tool Allowlists · Day 64: Secret-Aware Context Filters
Last updated September 11, 2026
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
