ComputeAdvanced14 min read

    AWS ECS Security Best Practices

    Tarek Cheikh

    Founder & AWS Security Expert

    View Security Card

    Amazon Elastic Container Service (ECS) is the backbone of containerized workloads on AWS, running millions of containers daily across EC2 and Fargate launch types. But containers introduce a unique attack surface -- shared kernel namespaces, image supply chain risks, over-privileged task roles, and runtime threats that traditional VM security does not address.

    In August 2025, researchers at Sweet Security disclosed ECScape at Black Hat USA -- a vulnerability in the undocumented ECS Agent Communication Service (ACS) protocol that allows a compromised container on an EC2 host to steal IAM credentials from neighboring tasks without ever escaping the container. The attack works by manipulating network traffic to impersonate the ECS agent, exploiting default behaviors of ECS on EC2. Then in November 2025, AWS GuardDuty detected an active cryptomining campaign where attackers used compromised IAM credentials to spin up over 50 ECS clusters per account, deploying the malicious Docker Hub image yenik65958/secret:user (over 100,000 pulls) to Fargate tasks and mining cryptocurrency within 10 minutes of initial access. A key technique observed was the use of ModifyInstanceAttribute with disable API termination set to true, forcing victims to re-enable API termination before they could delete the compromised resources.

    These incidents underscore that securing ECS requires a layered approach spanning identity, network, image supply chain, runtime monitoring, and compliance automation. This guide covers 12 battle-tested best practices with real CLI commands and the latest 2025-2026 updates from AWS.

    1. Separate Task Roles from Execution Roles

    ECS has two distinct IAM roles that are frequently confused, leading to over-privileged containers:

    • Task Role (taskRoleArn): The IAM role your application code assumes at runtime. This is what your container uses to call AWS APIs (S3, DynamoDB, SQS, etc.).
    • Execution Role (executionRoleArn): The IAM role the ECS agent uses to pull images from ECR, fetch secrets, and write logs. Your application never sees these credentials.

    The danger: many teams assign a single over-permissive role for both purposes. If any container is compromised -- as in the November 2025 cryptomining campaign -- the attacker inherits every permission from both roles simultaneously.

    Implementation

    # Create a minimal task role (application permissions only)
    aws iam create-role   --role-name my-app-task-role   --assume-role-policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
          "Effect": "Allow",
          "Principal": {"Service": "ecs-tasks.amazonaws.com"},
          "Action": "sts:AssumeRole"
        }]
      }'
    
    # Attach only the permissions your app needs -- specific ARNs, never wildcards
    aws iam put-role-policy   --role-name my-app-task-role   --policy-name app-permissions   --policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
          "Effect": "Allow",
          "Action": ["s3:GetObject"],
          "Resource": "arn:aws:s3:::my-app-bucket/*"
        }]
      }'
    
    # Create a separate execution role (ECR pull + logs only)
    aws iam create-role   --role-name my-app-execution-role   --assume-role-policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
          "Effect": "Allow",
          "Principal": {"Service": "ecs-tasks.amazonaws.com"},
          "Action": "sts:AssumeRole"
        }]
      }'
    
    aws iam attach-role-policy   --role-name my-app-execution-role   --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

    Security Hub Controls: [ECS.4] (containers should run as non-privileged), [ECS.17] (task definitions should not share the host process namespace). Never assign AdministratorAccess or broad *:* policies to task roles. Use IAM Access Analyzer to generate least-privilege policies from CloudTrail usage data.

    Key principle: Each microservice should have its own task role with the minimum permissions it needs. Never share a single task role across multiple services -- this violates least privilege and increases blast radius during a compromise.

    2. Run Containers as Non-Root

    By default, containers run as root (UID 0). If an attacker exploits an application vulnerability, they gain root-level access inside the container -- and potentially to the host via kernel exploits or misconfigurations like shared namespaces.

    Implementation

    In your Dockerfile:

    # Create a non-root user
    RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
    
    # Set ownership of application files
    COPY --chown=appuser:appgroup . /app
    
    # Switch to non-root user
    USER appuser
    
    # Application runs as UID != 0
    CMD ["node", "server.js"]

    In your ECS task definition, enforce read-only root filesystem and drop all Linux capabilities:

    {
      "containerDefinitions": [{
        "name": "my-app",
        "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest",
        "user": "appuser",
        "readonlyRootFilesystem": true,
        "linuxParameters": {
          "capabilities": {
            "drop": ["ALL"]
          }
        },
        "mountPoints": [{
          "sourceVolume": "tmp-volume",
          "containerPath": "/tmp",
          "readOnly": false
        }]
      }],
      "volumes": [{
        "name": "tmp-volume"
      }]
    }

    Security Hub Control [ECS.5]: ECS containers should be limited to read-only access to root filesystems. Combined with dropping all Linux capabilities and running as non-root, this drastically limits what an attacker can do post-compromise. If your application needs to write temporary files, mount a writable /tmp volume as shown above.

    3. Enable ECR Image Scanning with Amazon Inspector

    Container images are built from layers of dependencies, each potentially harboring known vulnerabilities (CVEs). Without scanning, you are deploying blind.

    Implementation

    # Enable enhanced scanning with Amazon Inspector (replaces basic scanning)
    aws ecr put-registry-scanning-configuration   --scan-type ENHANCED   --rules '[{
        "repositoryFilters": [{"filter": "*", "filterType": "WILDCARD"}],
        "scanFrequency": "CONTINUOUS_SCAN"
      }]'
    
    # Verify scanning configuration
    aws ecr get-registry-scanning-configuration
    
    # Check scan findings for a specific image
    aws ecr describe-image-scan-findings   --repository-name my-app   --image-id imageTag=latest
    
    # Clean up old untagged images to reduce attack surface
    aws ecr put-lifecycle-policy   --repository-name my-app   --lifecycle-policy-text '{
        "rules": [{
          "rulePriority": 1,
          "description": "Expire untagged images older than 14 days",
          "selection": {
            "tagStatus": "untagged",
            "countType": "sinceImagePushed",
            "countUnit": "days",
            "countNumber": 14
          },
          "action": {"type": "expire"}
        }]
      }'

    Enhanced scanning with Amazon Inspector provides continuous monitoring (not just scan-on-push), covers both OS packages and application dependencies (Java, Python, Node.js, Go, .NET), and integrates findings directly into Security Hub.

    CI/CD integration: Add a gate in your pipeline that fails the build if critical or high-severity CVEs are found. Use aws ecr describe-image-scan-findings with --query to filter by severity and block deployment of vulnerable images.

    4. Inject Secrets Securely (Never Use Environment Variables)

    Storing secrets in plaintext environment variables exposes them in task definitions, CloudWatch logs, container inspect output, and the ECS console. The November 2025 cryptomining campaign demonstrated how compromised credentials can be weaponized in minutes.

    Implementation

    # Store a secret in Secrets Manager
    aws secretsmanager create-secret   --name /myapp/database-password   --secret-string '{"password":"MyS3cur3P@ss!"}'
    
    # Or use SSM Parameter Store (cheaper for non-rotating secrets)
    aws ssm put-parameter   --name /myapp/api-key   --type SecureString   --value "sk-abc123..."

    Reference secrets in your task definition using secrets (not environment):

    {
      "containerDefinitions": [{
        "name": "my-app",
        "secrets": [
          {
            "name": "DB_PASSWORD",
            "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:/myapp/database-password:password::"
          },
          {
            "name": "API_KEY",
            "valueFrom": "arn:aws:ssm:us-east-1:123456789012:parameter/myapp/api-key"
          }
        ]
      }]
    }

    The execution role needs permission to fetch these secrets:

    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": [
          "secretsmanager:GetSecretValue",
          "ssm:GetParameters"
        ],
        "Resource": [
          "arn:aws:secretsmanager:us-east-1:123456789012:secret:/myapp/*",
          "arn:aws:ssm:us-east-1:123456789012:parameter/myapp/*"
        ]
      }]
    }

    Security Hub Control [ECS.8]: Secrets should not be passed as container environment variables. This control specifically flags task definitions that use the environment field for sensitive values instead of the secrets field. Use Secrets Manager for credentials that need automatic rotation and SSM Parameter Store for static configuration values.

    5. Enable GuardDuty ECS Runtime Monitoring

    Static scanning catches known CVEs, but runtime threats -- cryptominers, reverse shells, lateral movement -- require behavioral detection. In December 2025, AWS extended GuardDuty Extended Threat Detection to ECS, introducing the critical-severity finding AttackSequence:ECS/CompromisedCluster that correlates multiple signals across runtime activity, malware detections, VPC Flow Logs, DNS queries, and CloudTrail events.

    Implementation

    # Enable GuardDuty ECS Runtime Monitoring
    aws guardduty update-detector   --detector-id $(aws guardduty list-detectors --query "DetectorIds[0]" --output text)   --features '[{
        "Name": "RUNTIME_MONITORING",
        "Status": "ENABLED",
        "AdditionalConfiguration": [{
          "Name": "ECS_FARGATE_AGENT_MANAGEMENT",
          "Status": "ENABLED"
        }]
      }]'
    
    # Verify runtime monitoring status
    aws guardduty get-detector   --detector-id $(aws guardduty list-detectors --query "DetectorIds[0]" --output text)   --query "Features[?Name=='RUNTIME_MONITORING']"

    What GuardDuty Detects at Runtime

    • Cryptomining: Process execution and DNS queries to mining pools (the exact behavior seen in the November 2025 campaign)
    • Reverse shells: Outbound network connections with suspicious patterns
    • Privilege escalation: Unusual capability usage or namespace manipulation
    • Credential theft: Anomalous IMDS access or credential exfiltration attempts
    • Malware: Known malicious file hashes and behaviors

    For Fargate tasks, the GuardDuty security agent is fully managed -- no installation, configuration, or updates required. For EC2 launch type, the agent deploys automatically as a sidecar container when you enable the feature. Findings map to MITRE ATT&CK tactics and integrate with Security Hub, EventBridge, and Amazon Detective for automated response and investigation.

    6. Use awsvpc Network Mode with Task-Level Security Groups

    The awsvpc network mode gives each ECS task its own elastic network interface (ENI) and private IP address, enabling task-level security groups. This is the only network mode supported by Fargate and the most secure option for EC2 launch type.

    Implementation

    # Create a security group for a specific microservice
    aws ec2 create-security-group   --group-name ecs-api-service-sg   --description "Security group for API service tasks"   --vpc-id vpc-0123456789abcdef0
    
    # Allow only ALB traffic on port 8080
    aws ec2 authorize-security-group-ingress   --group-id sg-0123456789abcdef0   --protocol tcp   --port 8080   --source-group sg-ALB-SECURITY-GROUP
    
    # Register task definition with awsvpc mode
    aws ecs register-task-definition   --family my-api-service   --network-mode awsvpc   --requires-compatibilities FARGATE   --cpu "256" --memory "512"   --container-definitions '[{
        "name": "api",
        "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/api:latest",
        "portMappings": [{"containerPort": 8080, "protocol": "tcp"}]
      }]'
    
    # Create service with security group and private subnets
    aws ecs create-service   --cluster my-cluster   --service-name api-service   --task-definition my-api-service   --network-configuration '{
        "awsvpcConfiguration": {
          "subnets": ["subnet-private-1", "subnet-private-2"],
          "securityGroups": ["sg-0123456789abcdef0"],
          "assignPublicIp": "DISABLED"
        }
      }'

    Security Hub Control [ECS.2]: ECS services should not have public IP addresses assigned automatically. Always deploy tasks in private subnets with assignPublicIp: DISABLED and route outbound traffic through NAT gateways or VPC endpoints.

    Best practice: Each microservice should have its own security group. Never share a single security group across all tasks -- this defeats the purpose of network micro-segmentation. Use security group references (not CIDR ranges) to restrict inter-service communication to only the paths your architecture requires.

    7. Mitigate ECScape: Restrict Host Namespace Access

    The ECScape vulnerability, presented at Black Hat USA 2025, demonstrated that a compromised container running on an EC2 host can steal IAM credentials from neighboring ECS tasks. The attack exploits the undocumented Agent Communication Service (ACS) WebSocket protocol by manipulating network traffic from within the container to impersonate the ECS agent -- all without requiring a traditional container escape. Unlike typical container escapes that require host-level access, ECScape operates entirely within the container's namespace.

    AWS stated that this behavior does not present a security concern and updated documentation rather than issuing a patch. No CVE was assigned. This makes proactive mitigation essential.

    Mitigation Strategies

    {
      "containerDefinitions": [{
        "name": "my-app",
        "privileged": false,
        "linuxParameters": {
          "capabilities": {
            "drop": ["ALL"],
            "add": []
          },
          "initProcessEnabled": true
        }
      }],
      "pidMode": "task",
      "ipcMode": "task"
    }
    • Use Fargate for sensitive workloads. Fargate provides hardware-level isolation between tasks using Firecracker microVMs, completely eliminating the shared-host attack vector that ECScape exploits.
    • Set pidMode and ipcMode to task instead of host. This prevents containers from seeing processes or shared memory in other tasks on the same instance.
    • Never run privileged containers. Set "privileged": false explicitly and drop all Linux capabilities.
    • Restrict IMDS access. ECScape requires EC2 instance role credentials obtained via IMDS. Block IMDS access from containers by requiring IMDSv2 with a hop limit of 1.
    • Avoid co-locating high- and low-privilege tasks. Never run tasks with elevated IAM permissions (database admin, secrets access) alongside untrusted or externally-facing workloads on the same EC2 instances.
    # Enforce IMDSv2 with hop limit 1 on ECS EC2 instances
    # (prevents containers from reaching IMDS through the container network layer)
    aws ec2 modify-instance-metadata-options   --instance-id i-0123456789abcdef0   --http-tokens required   --http-put-response-hop-limit 1
    
    # Set ECS agent to disable privileged containers on the host
    # In /etc/ecs/ecs.config:
    # ECS_DISABLE_PRIVILEGED=true
    
    # Set up CloudTrail alerts to detect unusual usage of IAM roles
    aws cloudwatch put-metric-alarm   --alarm-name ecs-unusual-role-assumption   --metric-name UnauthorizedAttemptCount   --namespace CloudTrailMetrics   --statistic Sum   --period 300   --threshold 1   --comparison-operator GreaterThanOrEqualToThreshold   --evaluation-periods 1   --alarm-actions arn:aws:sns:us-east-1:123456789012:security-alerts

    Security Hub Control [ECS.3]: ECS task definitions should not share the host's process namespace. This control flags task definitions with pidMode set to host.

    8. Centralize Logging with FireLens and Container Insights

    Without centralized logging, investigating a container compromise is nearly impossible. Containers are ephemeral -- when a task stops, its local logs disappear. The November 2025 cryptomining campaign was detected in part because GuardDuty correlated runtime events with CloudTrail logs -- organizations without centralized logging would have been blind to the attack.

    Implementation with FireLens

    {
      "containerDefinitions": [
        {
          "name": "log-router",
          "image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:stable",
          "essential": true,
          "firelensConfiguration": {
            "type": "fluentbit",
            "options": {
              "config-file-type": "file",
              "config-file-value": "/fluent-bit/configs/parse-json.conf"
            }
          }
        },
        {
          "name": "my-app",
          "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest",
          "logConfiguration": {
            "logDriver": "awsfirelens",
            "options": {
              "Name": "cloudwatch_logs",
              "region": "us-east-1",
              "log_group_name": "/ecs/my-app",
              "log_stream_prefix": "app-",
              "auto_create_group": "true"
            }
          }
        }
      ]
    }

    Enable Container Insights

    # Enable enhanced Container Insights on an ECS cluster
    aws ecs update-cluster-settings   --cluster my-cluster   --settings '[{"name": "containerInsights", "value": "enhanced"}]'
    
    # Verify Container Insights is enabled
    aws ecs describe-clusters   --clusters my-cluster   --query "clusters[0].settings"

    Security Hub Control [ECS.12]: ECS clusters should use Container Insights. Container Insights provides CPU, memory, network, and storage metrics at the task and service level, plus integration with CloudWatch for alarms and dashboards.

    For security-critical environments, route logs to both CloudWatch (for real-time alerting) and S3 (for long-term retention and forensics). Use FireLens to fan out logs to multiple destinations simultaneously.

    9. Encrypt EFS Volumes for Fargate Tasks

    ECS Fargate tasks can mount Amazon EFS file systems for persistent storage. Without encryption, data at rest on the file system and data in transit between the task and EFS are exposed.

    Implementation

    # Create an encrypted EFS file system
    aws efs create-file-system   --encrypted   --kms-key-id arn:aws:kms:us-east-1:123456789012:key/my-efs-key   --performance-mode generalPurpose   --tags Key=Name,Value=ecs-app-storage
    
    # Create a mount target in each private subnet
    aws efs create-mount-target   --file-system-id fs-0123456789abcdef0   --subnet-id subnet-private-1   --security-groups sg-efs-access
    
    # Create an EFS access point for the application
    aws efs create-access-point   --file-system-id fs-0123456789abcdef0   --posix-user '{"Uid": 1000, "Gid": 1000}'   --root-directory '{"Path": "/app-data", "CreationInfo": {"OwnerUid": 1000, "OwnerGid": 1000, "Permissions": "750"}}'

    In your task definition, enforce in-transit encryption:

    {
      "volumes": [{
        "name": "app-data",
        "efsVolumeConfiguration": {
          "fileSystemId": "fs-0123456789abcdef0",
          "transitEncryption": "ENABLED",
          "transitEncryptionPort": 2999,
          "authorizationConfig": {
            "accessPointId": "fsap-0123456789abcdef0",
            "iam": "ENABLED"
          }
        }
      }]
    }

    Setting iam: ENABLED ensures that the task role must have elasticfilesystem:ClientMount and elasticfilesystem:ClientWrite permissions, adding an IAM-based access control layer on top of POSIX permissions. Combined with EFS access points, this provides fine-grained isolation between tasks sharing the same file system. Use KMS customer-managed keys for encryption to maintain full control over key rotation and access policies.

    10. Enable TLS for Service-to-Service Communication

    By default, inter-service traffic within a VPC is unencrypted. If an attacker gains network access (via a compromised container or VPC misconfiguration), they can sniff traffic between microservices.

    ECS Service Connect with TLS

    ECS Service Connect provides built-in service discovery and traffic management with optional TLS encryption using AWS Private Certificate Authority (PCA) short-lived certificates:

    # Create a Cloud Map namespace for Service Connect
    aws servicediscovery create-http-namespace   --name my-app.local   --description "ECS Service Connect namespace"
    
    # Create an ECS service with Service Connect and TLS
    aws ecs create-service   --cluster my-cluster   --service-name api-service   --task-definition my-api-service   --service-connect-configuration '{
        "enabled": true,
        "namespace": "arn:aws:servicediscovery:us-east-1:123456789012:namespace/ns-EXAMPLE",
        "services": [{
          "portName": "api",
          "discoveryName": "api-service",
          "clientAliases": [{"port": 8080, "dnsName": "api.my-app.local"}],
          "tls": {
            "issuerCertificateAuthority": {
              "awsPcaAuthorityArn": "arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/ca-EXAMPLE"
            },
            "roleArn": "arn:aws:iam::123456789012:role/ServiceConnectTLSRole"
          }
        }]
      }'

    Service Connect manages the Envoy proxy sidecar automatically, handles certificate rotation via ACM PCA, and requires no application code changes. For environments requiring mutual TLS (mTLS), use Application Load Balancer mTLS termination with ACM PCA-issued client certificates.

    Important: AWS App Mesh will be discontinued on September 30, 2026. If you are using App Mesh for mTLS, migrate to ECS Service Connect. For new deployments, Service Connect should be your default choice.

    11. Sign and Verify Container Images

    Without image signing, there is no guarantee that the container image running in production is the same image that passed your CI/CD security checks. An attacker who compromises your ECR repository or CI pipeline can inject malicious images -- exactly the supply chain attack pattern seen in the November 2025 campaign where the malicious yenik65958/secret image was pulled from Docker Hub.

    Implementation with AWS Signer (Managed Signing)

    # Create a signing profile
    aws signer put-signing-profile   --profile-name ecs-production   --platform-id Notation-OCI-SHA384-ECDSA
    
    # Sign an image with Notation CLI and AWS Signer plugin
    notation sign   --plugin com.amazonaws.signer.notation.plugin   --id arn:aws:signer:us-east-1:123456789012:/signing-profiles/ecs-production   123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest
    
    # Verify an image signature
    notation verify   123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest   --trust-policy ./trust-policy.json
    
    # Alternative: use cosign for Sigstore-based verification
    cosign verify   --key awskms:///arn:aws:kms:us-east-1:123456789012:key/my-signing-key   123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest

    Managed Signing (Recommended)

    Amazon ECR now supports managed signing, where images are automatically signed during push without requiring client-side tools like Notation or cosign. AWS Signer handles key material, certificate lifecycle management, key generation, secure storage, and rotation. For existing pipelines that need manual control, use the Notation CLI with the AWS Signer plugin as shown above.

    Verification at Deployment

    Use ECS service deployment lifecycle hooks with Lambda to verify image signatures before tasks start. If the signature is invalid, the Lambda function kills the tasks and sends an alert via SNS. Combine image signing with ECR immutable tags to prevent tag overwriting, ensuring that a signed v1.2.3 tag always points to the same verified image digest.

    12. Automate Compliance with Security Hub ECS Controls

    AWS Security Hub provides automated, continuous evaluation of your ECS configuration against the AWS Foundational Security Best Practices (FSBP) standard.

    Key ECS Controls

    Control ID Description Severity
    [ECS.4] Containers should run as non-privileged High
    [ECS.2] ECS services should not have public IP addresses assigned automatically High
    [ECS.3] Task definitions should not share the host's process namespace High
    [ECS.5] Containers should be limited to read-only access to root filesystems High
    [ECS.8] Secrets should not be passed as container environment variables High
    [ECS.10] Fargate services should run on the latest Fargate platform version Medium
    [ECS.12] ECS clusters should use Container Insights Medium

    Enable and Audit

    # Enable AWS Foundational Security Best Practices standard
    aws securityhub batch-enable-standards   --standards-subscription-requests '[{
        "StandardsArn": "arn:aws:securityhub:us-east-1::standards/aws-foundational-security-best-practices/v/1.0.0"
      }]'
    
    # List all failing ECS controls
    aws securityhub get-findings   --filters '{
        "ComplianceStatus": [{"Value": "FAILED", "Comparison": "EQUALS"}],
        "ResourceType": [{"Value": "AwsEcsTaskDefinition", "Comparison": "EQUALS"}]
      }'   --query "Findings[].{Control:Compliance.SecurityControlId,Resource:Resources[0].Id,Status:Compliance.Status}"
    
    # Get Fargate platform version compliance
    aws securityhub get-findings   --filters '{
        "ComplianceSecurityControlId": [{"Value": "ECS.10", "Comparison": "EQUALS"}],
        "ComplianceStatus": [{"Value": "FAILED", "Comparison": "EQUALS"}]
      }'

    Security Hub Control [ECS.10]: Fargate services should run on the latest platform version. Older platform versions may lack security patches and features. Always specify LATEST or pin to the current version (1.4.0 for Linux) and update regularly.

    Integrate Security Hub findings with EventBridge to trigger automated remediation -- for example, automatically stopping a service that deploys a task definition with pidMode: host or secrets in environment variables.


    Common ECS Misconfigurations

    Misconfiguration Risk Detection
    Shared task role across services Blast radius expansion on compromise IAM Access Analyzer unused permissions
    Containers running as root Privilege escalation to host Security Hub [ECS.4]
    Secrets in environment variables Credential exposure in logs and console Security Hub [ECS.8]
    pidMode: host on task definitions Cross-container process visibility (ECScape) Security Hub [ECS.3]
    Public IP on Fargate tasks Direct internet exposure Security Hub [ECS.2]
    No image scanning enabled Deploying images with known CVEs Inspector dashboard
    Outdated Fargate platform version Missing security patches Security Hub [ECS.10]

    Quick Reference Checklist

    # Practice Priority
    1Separate task roles from execution rolesCritical
    2Run containers as non-rootCritical
    3Enable ECR image scanning with InspectorCritical
    4Inject secrets via Secrets Manager/SSMCritical
    5Enable GuardDuty runtime monitoringHigh
    6Use awsvpc mode with task-level security groupsHigh
    7Mitigate ECScape (restrict namespaces, use Fargate)High
    8Centralize logging with FireLens and Container InsightsHigh
    9Encrypt EFS volumes (at-rest and in-transit)Medium
    10Enable TLS for service-to-service communicationMedium
    11Sign and verify container imagesMedium
    12Automate compliance with Security Hub ECS controlsHigh

    Related Resources

    Go Deeper: The State of AWS Security 2026

    This article is just the start. Get the full picture with our free whitepaper - 8 chapters covering IAM, S3, VPC, monitoring, agentic AI security, compliance, and a prioritized action plan with 50+ CLI commands.

    ECSContainersFargateECRTask RolesContainer SecurityGuardDutyDockerImage ScanningService Connect