AWS Security Hub · ECS
ECS.9: A task definition has no logging configuration
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub ECS.9 check?
ECS.9 flags the latest active revision of a task definition that has no logConfiguration defined, or where any container's logDriver is null. It wants every container wired to a log destination before it ever runs.
Why does ECS.9 matter?
A logless container is operationally and forensically blind. When a service throws a 500 at 3am, the on-call engineer has nothing to read, so mean-time-to-resolution stretches from minutes to hours as every theory has to be reproduced live. The same gap means a security incident leaves no trail and an audit has nothing to sample. ECS.9 maps to a stack of NIST 800-53 audit-and-accountability controls for exactly that reason.
How do I fix ECS.9?
- Add a logConfiguration block to every container, typically with the awslogs driver pointing at a CloudWatch Logs group.
- Pre-create the log group (or set awslogs-create-group) and grant the task execution role logs:CreateLogStream and logs:PutLogEvents.
- Register the new revision and redeploy, then confirm log streams appear.
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.9 a false positive?
AWS itself notes the legitimate exception: if you run a logging solution that doesn't have to be declared in the task definition (a sidecar that tails files, a node-level agent like Fluent Bit or the CloudWatch agent collecting stdout, or a third-party platform scraping the container) then a container with no logConfiguration is still fully logged, yet ECS.9 fails because it only inspects the logDriver field on each container definition. Confirm the logs are actually being captured and delivered, then set the finding to SUPPRESSED in Security Hub and record the out-of-band pipeline, rather than bolting an unused awslogs driver onto the task just to clear the control.
More ECS controls
- ECS.2 An ECS service auto-assigns public IPs to tasks
- ECS.3 A task definition shares the host PID namespace
- 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.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