AWS Security ChangesHomeSearch

AWS code-library high security documentation change

Service: code-library · 2026-05-01 · Security-related high

File: code-library/latest/ug/ecs_example_ecs_GettingStarted_086_section.md

Summary

Added multiple security enhancements including input validation for AWS resource IDs, command injection prevention through proper quoting, JSON validation, secure file deletion, and container image hardening

Security assessment

Changes include concrete security improvements: 1) Input validation for security group/VPC/ENI IDs prevents command injection via malformed inputs 2) Quoting variables in AWS commands mitigates shell injection attacks 3) Secure file deletion (shred) prevents sensitive data leakage 4) JSON validation blocks malformed policy/task definitions 5) Switching from 'latest' to versioned container image reduces supply chain risks 6) Added security group format validation prevents AWS API errors that could leave resources exposed

Diff

diff --git a/code-library/latest/ug/ecs_example_ecs_GettingStarted_086_section.md b/code-library/latest/ug/ecs_example_ecs_GettingStarted_086_section.md
index 3adb01dff..fbbfa7be1 100644
--- a//code-library/latest/ug/ecs_example_ecs_GettingStarted_086_section.md
+++ b//code-library/latest/ug/ecs_example_ecs_GettingStarted_086_section.md
@@ -39,0 +40 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Security improvements applied
@@ -60 +61 @@ 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
@@ -63,0 +65,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
+        
@@ -102,0 +111,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"
+    }
+    
@@ -108,0 +127,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
+        
@@ -143,0 +168,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
+        
@@ -147 +177 @@ 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
@@ -177,2 +207,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"
@@ -187 +218 @@ 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
@@ -189 +220 @@ 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"
@@ -192 +223 @@ 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"
@@ -195 +226 @@ 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"
@@ -208 +239 @@ 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"
@@ -212 +243 @@ 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
@@ -235 +266 @@ 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
@@ -278,0 +310,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
+    
@@ -287 +323 @@ 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
@@ -302,0 +339,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
+        
@@ -307,2 +350,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
@@ -319 +362 @@ 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")
@@ -330 +373 @@ 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
@@ -342 +385 @@ 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",
@@ -354 +397,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"
+                    }
+                }
@@ -359,0 +411,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
+    
@@ -363,2 +421,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
@@ -379,0 +438,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
+    
@@ -385 +450 @@ 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")
@@ -388,3 +453,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
@@ -399 +470 @@ 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"
@@ -427 +498 @@ 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\"}}'"
@@ -443 +514 @@ 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"
@@ -446 +517 @@ 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)
@@ -455 +526 @@ 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)
@@ -460,0 +532,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
+    
@@ -464 +541 @@ 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)
@@ -467,0 +545,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=""
@@ -476,0 +559 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    fi
@@ -483 +566 @@ 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"