AWS Security ChangesHomeSearch

AWS ec2 documentation change

Service: ec2 · 2026-05-01 · Documentation low

File: ec2/latest/devguide/example_ecs_GettingStarted_086_section.md

Summary

Added multiple security improvements to an ECS Fargate example script including input validation, secure variable quoting, JSON validation, secure file deletion, and security group/VPC ID format validation

Security assessment

The changes add security best practices to an example script but don't address a specific security vulnerability or incident. Changes include: 1) Input validation for commands, security group IDs, VPC IDs, ENI IDs, and IP addresses; 2) Secure file deletion using shred; 3) JSON validation before use; 4) Variable quoting to prevent injection; 5) More specific container image tag (2.4-alpine vs latest). These are preventive security measures rather than fixes for existing issues.

Diff

diff --git a/ec2/latest/devguide/example_ecs_GettingStarted_086_section.md b/ec2/latest/devguide/example_ecs_GettingStarted_086_section.md
index efb6b9ba8..7205043c1 100644
--- a//ec2/latest/devguide/example_ecs_GettingStarted_086_section.md
+++ b//ec2/latest/devguide/example_ecs_GettingStarted_086_section.md
@@ -37,0 +38 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Security improvements applied
@@ -58 +59 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Function to log and execute commands
+    # Function to log and execute commands with input validation
@@ -61,0 +63,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        
+        # Validate that cmd is not empty
+        if [[ -z "$cmd" ]]; then
+            echo "ERROR: Command is empty"
+            return 1
+        fi
+        
@@ -100,0 +109,10 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Function to safely extract JSON values
+    safe_json_extract() {
+        local json="$1"
+        local key="$2"
+        local value
+        
+        value=$(echo "$json" | grep -o "\"$key\": \"[^\"]*\"" | cut -d'"' -f4 2>/dev/null || echo "")
+        echo "$value"
+    }
+    
@@ -106,0 +125,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        # Validate security group ID format
+        if [[ ! "$security_group_id" =~ ^sg-[a-z0-9]{8,17}$ ]]; then
+            echo "ERROR: Invalid security group ID format: $security_group_id"
+            return 1
+        fi
+        
@@ -141,0 +166,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        # Validate security group ID format
+        if [[ ! "$security_group_id" =~ ^sg-[a-z0-9]{8,17}$ ]]; then
+            echo "ERROR: Invalid security group ID format: $security_group_id"
+            return 1
+        fi
+        
@@ -145 +175 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            if execute_command "aws ec2 delete-security-group --group-id $security_group_id" "Delete security group (attempt $attempt)"; then
+            if execute_command "aws ec2 delete-security-group --group-id '$security_group_id'" "Delete security group (attempt $attempt)"; then
@@ -175,2 +205,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        echo "Do you want to clean up all created resources? (y/n): "
-        read -r CLEANUP_CHOICE
+        echo "Auto-confirming cleanup of all created resources..."
+        
+        CLEANUP_CHOICE="y"
@@ -185 +216 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                if execute_command "aws ecs update-service --cluster $CLUSTER_NAME --service $SERVICE_NAME --desired-count 0" "Scale service to 0 tasks"; then
+                if execute_command "aws ecs update-service --cluster '$CLUSTER_NAME' --service '$SERVICE_NAME' --desired-count 0" "Scale service to 0 tasks"; then
@@ -187 +218 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                    execute_command "aws ecs wait services-stable --cluster $CLUSTER_NAME --services $SERVICE_NAME" "Wait for service to stabilize"
+                    execute_command "aws ecs wait services-stable --cluster '$CLUSTER_NAME' --services '$SERVICE_NAME'" "Wait for service to stabilize"
@@ -190 +221 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                    execute_command "aws ecs delete-service --cluster $CLUSTER_NAME --service $SERVICE_NAME" "Delete ECS service"
+                    execute_command "aws ecs delete-service --cluster '$CLUSTER_NAME' --service '$SERVICE_NAME'" "Delete ECS service"
@@ -193 +224 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                    execute_command "aws ecs delete-service --cluster $CLUSTER_NAME --service $SERVICE_NAME --force" "Force delete ECS service"
+                    execute_command "aws ecs delete-service --cluster '$CLUSTER_NAME' --service '$SERVICE_NAME' --force" "Force delete ECS service"
@@ -206 +237 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                execute_command "aws ecs delete-cluster --cluster $CLUSTER_NAME" "Delete ECS cluster"
+                execute_command "aws ecs delete-cluster --cluster '$CLUSTER_NAME'" "Delete ECS cluster"
@@ -210 +241 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            if [[ -n "$SECURITY_GROUP_ID" ]]; then
+            if [[ -n "$SECURITY_GROUP_ID" && "$SECURITY_GROUP_ID" != "None" ]]; then
@@ -233 +264 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                        execute_command "aws ecs deregister-task-definition --task-definition $revision_arn" "Deregister task definition $revision_arn" || true
+                        execute_command "aws ecs deregister-task-definition --task-definition '$revision_arn'" "Deregister task definition $revision_arn" || true
@@ -276,0 +308,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    if [[ ! "$ACCOUNT_ID" =~ ^[0-9]{12}$ ]]; then
+        echo "ERROR: Invalid AWS Account ID retrieved: $ACCOUNT_ID"
+        exit 1
+    fi
+    
@@ -285 +321 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Create trust policy
+        # Create trust policy with strict validation
@@ -300,0 +337,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        # Validate JSON before using
+        if ! jq empty trust-policy.json 2>/dev/null; then
+            echo "ERROR: Invalid JSON in trust policy"
+            rm -f trust-policy.json
+            exit 1
+        fi
+        
@@ -305,2 +348,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Clean up temporary file
-        rm -f trust-policy.json
+        # Clean up temporary file securely
+        shred -vfz -n 3 trust-policy.json 2>/dev/null || rm -f trust-policy.json
@@ -317 +360 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    CLUSTER_OUTPUT=$(execute_command "aws ecs create-cluster --cluster-name $CLUSTER_NAME" "Create ECS cluster")
+    CLUSTER_OUTPUT=$(execute_command "aws ecs create-cluster --cluster-name '$CLUSTER_NAME'" "Create ECS cluster")
@@ -328 +371 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create task definition JSON
+    # Create task definition JSON with validated inputs
@@ -340 +383 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                "image": "public.ecr.aws/docker/library/httpd:latest",
+                "image": "public.ecr.aws/docker/library/httpd:2.4-alpine",
@@ -352 +395,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                ]
+                ],
+                "logConfiguration": {
+                    "logDriver": "awslogs",
+                    "options": {
+                        "awslogs-group": "/ecs/fargate-sample",
+                        "awslogs-region": "us-east-1",
+                        "awslogs-stream-prefix": "ecs"
+                    }
+                }
@@ -357,0 +409,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Validate JSON before using
+    if ! jq empty task-definition.json 2>/dev/null; then
+        echo "ERROR: Invalid JSON in task definition"
+        rm -f task-definition.json
+        exit 1
+    fi
+    
@@ -361,2 +419,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Clean up temporary file
-    rm -f task-definition.json
+    # Clean up temporary file securely
+    shred -vfz -n 3 task-definition.json 2>/dev/null || rm -f task-definition.json
@@ -377,0 +436,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    
+    # Validate VPC ID format
+    if [[ ! "$VPC_ID" =~ ^vpc-[a-z0-9]{8,17}$ ]]; then
+        echo "ERROR: Invalid VPC ID format: $VPC_ID"
+        exit 1
+    fi
+    
@@ -383 +448 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    SECURITY_GROUP_OUTPUT=$(execute_command "aws ec2 create-security-group --group-name $SECURITY_GROUP_NAME --description 'Security group for ECS Fargate tutorial - HTTP access' --vpc-id $VPC_ID" "Create security group")
+    SECURITY_GROUP_OUTPUT=$(execute_command "aws ec2 create-security-group --group-name '$SECURITY_GROUP_NAME' --description 'Security group for ECS Fargate tutorial - HTTP access' --vpc-id '$VPC_ID'" "Create security group")
@@ -386,3 +451,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    SECURITY_GROUP_ID=$(echo "$SECURITY_GROUP_OUTPUT" | grep -o '"GroupId": "[^"]*"' | cut -d'"' -f4)
-    if [[ -z "$SECURITY_GROUP_ID" ]]; then
-        SECURITY_GROUP_ID=$(aws ec2 describe-security-groups --group-names "$SECURITY_GROUP_NAME" --query "SecurityGroups[0].GroupId" --output text)
+    SECURITY_GROUP_ID=$(echo "$SECURITY_GROUP_OUTPUT" | grep -o '"GroupId": "[^"]*"' | head -1 | cut -d'"' -f4)
+    if [[ -z "$SECURITY_GROUP_ID" || "$SECURITY_GROUP_ID" == "None" ]]; then
+        SECURITY_GROUP_ID=$(aws ec2 describe-security-groups --group-names "$SECURITY_GROUP_NAME" --filters "Name=vpc-id,Values=$VPC_ID" --query "SecurityGroups[0].GroupId" --output text)
+    fi
+    
+    # Validate security group ID format
+    if [[ ! "$SECURITY_GROUP_ID" =~ ^sg-[a-z0-9]{8,17}$ ]]; then
+        echo "ERROR: Invalid security group ID format: $SECURITY_GROUP_ID"
+        exit 1
@@ -397 +468 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    execute_command "aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 80 --cidr 0.0.0.0/0" "Add HTTP inbound rule to security group"
+    execute_command "aws ec2 authorize-security-group-ingress --group-id '$SECURITY_GROUP_ID' --protocol tcp --port 80 --cidr 0.0.0.0/0" "Add HTTP inbound rule to security group"
@@ -425 +496 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    SERVICE_CMD="aws ecs create-service --cluster $CLUSTER_NAME --service-name $SERVICE_NAME --task-definition $TASK_FAMILY --desired-count 1 --launch-type FARGATE --network-configuration '{\"awsvpcConfiguration\":{\"subnets\":[\"$(echo $SUBNET_IDS_COMMA | sed 's/,/","/g')\"],\"securityGroups\":[\"$SECURITY_GROUP_ID\"],\"assignPublicIp\":\"ENABLED\"}}'"
+    SERVICE_CMD="aws ecs create-service --cluster '$CLUSTER_NAME' --service-name '$SERVICE_NAME' --task-definition '$TASK_FAMILY' --desired-count 1 --launch-type FARGATE --network-configuration '{\"awsvpcConfiguration\":{\"subnets\":[\"$(echo "$SUBNET_IDS_COMMA" | sed 's/,/","/g')\"],\"securityGroups\":[\"$SECURITY_GROUP_ID\"],\"assignPublicIp\":\"ENABLED\"}}'"
@@ -441 +512 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    execute_command "aws ecs wait services-stable --cluster $CLUSTER_NAME --services $SERVICE_NAME" "Wait for service to stabilize"
+    execute_command "aws ecs wait services-stable --cluster '$CLUSTER_NAME' --services '$SERVICE_NAME'" "Wait for service to stabilize"
@@ -444 +515 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    TASK_ARN=$(aws ecs list-tasks --cluster $CLUSTER_NAME --service-name $SERVICE_NAME --query "taskArns[0]" --output text)
+    TASK_ARN=$(aws ecs list-tasks --cluster "$CLUSTER_NAME" --service-name "$SERVICE_NAME" --query "taskArns[0]" --output text)
@@ -453 +524 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    ENI_ID=$(aws ecs describe-tasks --cluster $CLUSTER_NAME --tasks $TASK_ARN --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" --output text)
+    ENI_ID=$(aws ecs describe-tasks --cluster "$CLUSTER_NAME" --tasks "$TASK_ARN" --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" --output text)
@@ -458,0 +530,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Validate ENI ID format
+    if [[ ! "$ENI_ID" =~ ^eni-[a-z0-9]{8,17}$ ]]; then
+        echo "ERROR: Invalid network interface ID format: $ENI_ID"
+        exit 1
+    fi
+    
@@ -462 +539 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    PUBLIC_IP=$(aws ec2 describe-network-interfaces --network-interface-ids $ENI_ID --query "NetworkInterfaces[0].Association.PublicIp" --output text)
+    PUBLIC_IP=$(aws ec2 describe-network-interfaces --network-interface-ids "$ENI_ID" --query "NetworkInterfaces[0].Association.PublicIp" --output text)
@@ -465,0 +543,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    else
+        # Validate IP format
+        if [[ ! "$PUBLIC_IP" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
+            echo "ERROR: Invalid IP address format: $PUBLIC_IP"
+            PUBLIC_IP=""
@@ -474,0 +557 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    fi
@@ -481 +564 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    execute_command "aws ecs describe-services --cluster $CLUSTER_NAME --services $SERVICE_NAME" "Get service details"
+    execute_command "aws ecs describe-services --cluster '$CLUSTER_NAME' --services '$SERVICE_NAME'" "Get service details"