How ECS Tasks Get IAM Credentials
Amazon ECS gives each running task two IAM roles. The task role defines what the containers inside that task can do in AWS. The task execution role is different: ECS itself uses it to pull container images and fetch secrets from Secrets Manager, then injects those secrets as environment variables. According to AWS documentation, containers never touch the task execution role directly.
Each task gets its own isolated role, even when multiple tasks share the same EC2 instance. That per-task isolation is the security model ECS customers rely on. ECS-cape breaks it.
Impersonating the ECS Agent via ACS Protocol
While building a detection sensor at Sweet Security, Haziz noticed the ECS agent opens a WebSocket passing sendCredentials=true and captured real task credentials flowing over it. His manager gave him three days to investigate.
“You have 3 days.” — Ron (Haziz’s manager)
IMDS is on by default in every ECS EC2 setup, so any task can retrieve the instance role credentials, which carry ecs:Poll and ecs:DiscoverPollEndpoint. The container introspection API returns the container instance ARN. With both, a task builds a valid ACS WebSocket request. AWS checks only for ecs:Poll, finds it, and pushes pre-assumed credentials for every co-resident task and task execution role.
Blast Radius: Cross-Task and Tenant Credential Theft
From one compromised task, an attacker reaches the IAM credentials of every other task on the same EC2 instance, including task execution role credentials (the ones ECS uses to fetch database passwords from Secrets Manager). Those were never supposed to be reachable by any container.
“there’s no misconfiguration needed” — Naor Haziz
In multi-tenant clusters, one tenant’s task can steal another’s secrets. Credentials arrive pre-assumed, so no AssumeRole call appears in CloudTrail under the attacker’s identity. IMDS is on by default and the instance role always carries the required permissions.
Attack Demo: Deleting S3 and Reading Secrets
Haziz set up three tasks: one deny-all task (the attacker), one with AmazonS3FullAccess, and one whose task execution role could read a Secrets Manager entry called “DB secret.”
From the deny-all shell, the S3 bucket deletion from zero-permission task (25:04) deleted the “Black Hat Las Vegas 2025” bucket. Then the Secrets Manager dump via task execution role hijack (26:43) printed the plain-text password. CloudTrail attributed both actions to the legitimate task identities. The attacker’s container appears nowhere in the logs.
Mitigations and AWS’s Official Position
AWS declined to issue a CVE. They updated documentation that previously stated containers can never access another task’s credentials to read: tasks on the same EC2 instance may potentially access credentials belonging to other tasks.
“Containers are not a security boundary.” — AWS (official statement)
Three defenses apply. Disable IMDS at the task level via iptables rules, not at the instance level (that breaks the ECS agent). Never grant a task role ecs:Poll or ecs:DiscoverPollEndpoint. Separate high and low privilege workloads onto different EC2 instances or clusters, and give each tenant its own cluster.
Q&A
How does IMDSv2 affect this vulnerability? Haziz said IMDSv2 shouldn’t change anything because the task runs on the same instance and can still get a valid token, though some hop-limit configurations might affect containers and the ECS agent may not support IMDSv2 anyway. ▶ 34:53
Is it ridiculous that AWS expects users to write their own IP tables rules to mitigate this? Haziz agreed the situation is frustrating, confirmed AWS’s official position is that it is the consumer’s security responsibility, and noted AWS said it was considering long-term platform fixes but had not committed to any. ▶ 35:34
Notable Quotes
You have 3 days. Ron (Haziz’s manager, quoted) · ▶ 9:17
Containers are not a security boundary. AWS (official statement, quoted by Haziz) · ▶ 33:16
there’s no misconfiguration needed Naor Haziz · ▶ 23:48
Key Takeaways
- Any ECS task on EC2 can impersonate the ECS agent and steal credentials from every co-resident task using only default instance permissions.
- CloudTrail logs the hijacked actions under the victim task’s identity, hiding the attacker’s container entirely.
- Disable IMDS access at the task level and never grant tasks the ecs:Poll or ecs:DiscoverPollEndpoint permissions.