AWS Security Hub · ECS
ECS.3: A task definition shares the host PID namespace
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub ECS.3 check?
ECS.3 evaluates the latest active revision of each task definition and fails when pidMode is set to host. That setting makes the task's containers share the EC2 instance's process namespace instead of getting their own isolated PID 1 and process tree.
Why does ECS.3 matter?
With the host PID namespace shared, one compromised process in the task can see, signal, and kill every process on the instance — including containers from other services scheduled onto the same box. It is also an information-disclosure path: command lines and environment visible through /proc routinely leak connection strings, tokens, and API keys from neighbouring processes.
How do I fix ECS.3?
- Remove the pidMode: host setting from the task definition, or set it to task if containers genuinely need a shared namespace with each other.
- Register the new revision and update the service to use it.
- Add a Config rule or admission check to block pidMode: host in future revisions.
Remediation script · bash
# Inventory: flag containers running as root or with a writable root filesystem.
for fam in $(aws ecs list-task-definition-families --status ACTIVE \
--query 'families[]' --output text); do
aws ecs describe-task-definition --task-definition "$fam" \
--query "taskDefinition.containerDefinitions[?user==null || user=='root' || user=='0' || readonlyRootFilesystem!=\`true\`].{Family:'$fam',Name:name,User:user,ReadOnly:readonlyRootFilesystem}" \
--output text
done
# Harden at the source. Dockerfile:
# RUN addgroup -S app && adduser -S -G app appuser
# USER appuser
# Task definition: non-root user, read-only root with one narrow tmpfs, secrets via ARN.
# "user": "1000:1000",
# "readonlyRootFilesystem": true,
# "mountPoints": [{ "sourceVolume": "scratch", "containerPath": "/tmp", "readOnly": false }],
# "secrets": [{ "name": "DB_PASSWORD",
# "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/checkout/db-AbCdEf" }]
# Register the hardened revision and roll it out (tasks only update on redeploy).
aws ecs register-task-definition --cli-input-json file://checkout-api-hardened.json
aws ecs update-service --cluster prod --service checkout-api \
--task-definition checkout-api --force-new-deployment Full walkthrough (console steps, edge cases and verification) in the lesson Harden ECS container workloads.
Is ECS.3 a false positive?
pidMode: host is almost always copied in from a debugging snippet rather than genuinely required. Real workloads that need cross-container visibility should use pidMode: task, which does not trip the control.
More ECS controls
- ECS.2 An ECS service auto-assigns public IPs to tasks
- ECS.4 A container runs in privileged mode
- ECS.5 A container has a writable root filesystem
- ECS.8 Secrets are passed as plaintext container env vars
- ECS.9 A task definition has no logging configuration
- ECS.10 Fargate services should run latest platform version
- ECS.12 ECS clusters should use Container Insights
- ECS.16 An ECS task set auto-assigns public IPs
- ECS.18 ECS task defs should encrypt EFS volumes in transit
- ECS.19 Capacity providers managed termination protection
- ECS.20 Linux containers should run as non-root users
- ECS.21 Windows containers should run as non-admin users