A prompt injection convinced your coding agent to print its task-role credentials into a “debug gist,” and twelve minutes later someone was calling RunInstances in a region you do not use. Humans read Slack. Attackers read IMDS. Amazon GuardDuty is the unfair advantage for agent fleets: continuous threat detection on CloudTrail, VPC Flow, and DNS — including finding types aimed at stolen credentials and unusual API sequences. Pair with CloudTrail Lake for deep forensics and Secrets Manager rotation so leaked secrets die fast — this post is the early-warning layer.
⚡ TL;DR: Enable GuardDuty in every agent account/OU (Org auto-enable). Prioritize finding types for credential exfil, unusual
AssumeRole, and anomalous S3/EC2 from agent roles. Auto-ticket HIGH/CRITICAL; revoke sessions and rotate secrets on match. Related: CloudTrail Lake IAM abuses, SCPs, IAM condition keys, WAF.
Why coding agents are credential candy
Agent runtimes concentrate power:
- Task roles that can write to S3, start CodeBuild, call Bedrock
- Long-lived forge tokens in Secrets Manager fetched every turn
- Logs/traces that accidentally capture
Authorizationheaders - Sandboxes that execute untrusted README / install scripts
Compromise modes you should assume: IMDS SSRF from a tool, secret printed into model output, stolen laptop CI role, or a dependency that exfils env. GuardDuty will not stop the first exfil packet — it will shorten the dwell time.
| Signal source | What GuardDuty sees | Agent relevance |
|---|---|---|
| CloudTrail | Unusual API / identity | Stolen keys, privilege abuse |
| VPC Flow | C2-like traffic patterns | Sandbox exfil |
| DNS logs | Algorithmic domains | Malware in install scripts |
| S3 protection | Anomalous object access | Artifact bucket theft |
| Malware protection | Infected objects / EBS | Uploaded agent artifacts |
Enable the right protections for agent OUs
Use Organizations delegated admin so every sandbox account inherits GuardDuty without tribal knowledge.
# ✅ org-level: enable GuardDuty + S3 + malware (adjust features to your plan)
aws guardduty create-detector --enable --features '[
{"Name":"S3_DATA_EVENTS","Status":"ENABLED"},
{"Name":"EBS_MALWARE_PROTECTION","Status":"ENABLED"},
{"Name":"RDS_LOGIN_EVENTS","Status":"ENABLED"},
{"Name":"LAMBDA_NETWORK_LOGS","Status":"ENABLED"}
]'
# ✅ preferred: enable via Organizations / delegated admin console or CFN
aws organizations enable-aws-service-access --service-principal guardduty.amazonaws.com
// ✅ EventBridge → Lambda ticket on HIGH findings for agent roles
const rule = new events.Rule(this, "GdAgentHigh", {
eventPattern: {
source: ["aws.guardduty"],
detailType: ["GuardDuty Finding"],
detail: {
severity: [{ numeric: [">=", 7] }],
resource: {
accessKeyDetails: {
userName: [{ prefix: "coding-agent-" }],
},
},
},
},
});
rule.addTarget(new targets.LambdaFunction(triageFn));
Finding types that matter for agents
Focus playbooks on:
- UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.* — classic stolen task-role keys used outside AWS
- PrivilegeEscalation / Persistence IAM findings — agent role trying to create users/keys
- Stealth:IAMUser/CloudTrailLoggingDisabled — someone covering tracks
- Impact / Crypto EC2 findings from sandbox accounts — mining after compromise
- Exfiltration:S3/ — bulk reads from artifact buckets
# ✅ triage stub: revoke + rotate on credential exfil finding
import boto3, json
gd = boto3.client("guardduty")
iam = boto3.client("iam")
sm = boto3.client("secretsmanager")
def handle_finding(finding: dict):
ftype = finding["type"]
if "InstanceCredentialExfiltration" in ftype or "UnauthorizedAccess:IAMUser" in ftype:
user = finding.get("resource", {}).get("accessKeyDetails", {}).get("userName")
access_key = finding.get("resource", {}).get("accessKeyDetails", {}).get("accessKeyId")
# ❌ Do not only "notify Slack" and wait for morning
if access_key:
iam.delete_access_key(UserName=user, AccessKeyId=access_key)
# force secret rotation for forge tokens used by that tenant's tools
sm.rotate_secret(SecretId=f"agent/{finding['accountId']}/github")
return {"action": "revoked_and_rotating", "type": ftype}
return {"action": "ticket_only", "type": ftype}
Correlate with CloudTrail Lake and IAM design
GuardDuty tells you something is wrong. CloudTrail Lake tells you every API the principal called. Standard response:
- GuardDuty HIGH → auto-create ticket + page
- Disable access keys / invalidate sessions (
AWSRevokeOlderSessionson role trust) - Query Lake for the principal’s 24h API set
- Confirm SCP / Cedar gaps; tighten IAM condition keys
-- ✅ CloudTrail Lake: APIs by a suspect agent role after finding time
SELECT eventTime, eventName, sourceIPAddress, userAgent, errorCode
FROM agent_trail_lake
WHERE userIdentity.sessionContext.sessionIssuer.arn LIKE '%coding-agent-tool%'
AND eventTime >= '2026-09-25T00:00:00Z'
ORDER BY eventTime ASC
LIMIT 500
Deny standing access keys for humans in agent accounts via SCPs. Prefer roles + short sessions. Sandbox egress should already be filtered (Network Firewall pattern in this batch’s companion post if published).
Suppress noise without suppressing compromise
Agent accounts generate unusual-but-benign API bursts (many AssumeRole, many S3 puts). Use suppression rules carefully:
- ✅ Suppress known canary account mining tests
- ❌ Suppress all
UnauthorizedAccessforcoding-agent-*roles - Tag findings with
tenant_idfrom role session tags when present for Insights joins
| Finding severity | Auto response | Human SLA |
|---|---|---|
| CRITICAL / HIGH credential | Revoke + rotate + page | 15 min |
| MEDIUM anomalous S3 | Ticket + Lake query | Same day |
| LOW recon | Weekly digest | Weekly |
Production checklist
- [ ] GuardDuty enabled Org-wide; delegated admin owned by security
- [ ] S3 / Malware / Lambda network features on in agent accounts as licensed
- [ ] EventBridge rules for HIGH+ findings involving agent role name prefixes
- [ ] Playbook: revoke keys,
AWSRevokeOlderSessions, rotate Secrets Manager, disable tool via AppConfig - [ ] CloudTrail Lake workbook for post-finding API reconstruction
- [ ] No long-lived IAM users in agent OUs; SCP deny
CreateAccessKeyfor agents - [ ] Findings exported to SIEM; retention ≥ 90 days
- [ ] Quarterly tabletop: simulated credential exfil from a Fargate task role
FAQ
Q: Does GuardDuty replace WAF or Firewall?
A: No — WAF is north-south HTTP, Firewall is egress policy, GuardDuty is detection on AWS telemetry. You want all three.
Q: Will it catch a secret pasted into ChatGPT?
A: Not directly. It catches use of stolen AWS credentials and many post-exploitation patterns. Prevent printouts with guardrails and secret hygiene; detect misuse with GuardDuty.
Q: How is this different from CloudTrail Lake alone?
A: Lake is query-when-you-suspect. GuardDuty is always-on detection with scored findings — then you use Lake to go deep.
GuardDuty turns credential theft against coding-agent fleets from a silent multi-day incident into a paged, automatable revoke-and-rotate loop. Enable it everywhere agents run, wire HIGH findings to action — not just dashboards — and keep CloudTrail Lake ready for the autopsy.
Runtime hygiene that makes GuardDuty findings rare
Detection is mandatory; reducing credential surface is cheaper:
- Prefer task roles over embedding cloud keys in sandbox env
- Block instance metadata hop abuse (
IMDSv2required, hop limit 1 on EC2; Fargate tasks already constrained — still treat SSRF as real) - Never echo secrets into model responses — strip with Bedrock ApplyGuardrail on tool I/O
- Scope S3 artifact prefixes per tenant (conditional writes) so a stolen role cannot list the whole bucket
- Cap spend so a compromised role mining EC2 hits Budgets / Cost Anomaly within minutes even if detection lags
// ✅ role trust session policy fragment forced on AssumeRole
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Deny",
"Action": ["iam:*", "organizations:*", "guardduty:DeleteDetector", "cloudtrail:StopLogging"],
"Resource": "*"
}]
}
When GuardDuty and Budgets fire together, assume compromise until Lake proves otherwise — dual-signal beats waiting for a perfect single finding.
Most viewed
- Python Decorators Explained: From Simple Wrappers to Production Patterns
- Spec-First AI Development: OpenAPI Remains the Only Source of Truth
- REST API Design Best Practices: The Patterns That Make APIs a Joy to Use
- Distributed Locks Reality Check: When Redis Redlock Is the Wrong Tool
- Python asyncio vs Threading: The Benchmark That Changes How You Think About Concurrency
Newly added
- AWS IAM Roles Anywhere: Cert-Based Creds for On-Prem Coding-Agent Runners
- Amazon Macie: Scan Coding-Agent Artifact Buckets for Leaked Secrets
- Amazon GuardDuty: Catch Compromised Coding-Agent Credentials Early
- AWS Network Firewall: Egress Filtering for Coding-Agent Sandboxes
- Amazon RDS Proxy: Connection Pooling for Coding-Agent Database Tools
Deep-dive PDF
Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.
Already subscribed? or open the subscribe page.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.