AWS Security ChangesHomeSearch

AWS lambda medium security documentation change

Service: lambda · 2026-05-01 · Security-related medium

File: lambda/latest/dg/example_cloudwatch_GettingStarted_031_section.md

Summary

Updated the CloudWatch dashboard creation script with security enhancements including strict file permissions, input validation, error handling improvements, unique resource naming, JSON escaping, and automated cleanup procedures.

Security assessment

The changes implement multiple security best practices: 1) Setting strict file permissions (chmod 600/700) prevents unauthorized access to logs/temporary files. 2) Input validation for AWS region format mitigates injection risks. 3) JSON escaping prevents potential code injection in dashboard creation. 4) Unique resource naming (timestamp suffixes) reduces residual resource conflicts. 5) Automated cleanup with 'trap' ensures resource deletion even on failures. These collectively address security weaknesses like insecure temporary files, injection vulnerabilities, and residual resource exposure.

Diff

diff --git a/lambda/latest/dg/example_cloudwatch_GettingStarted_031_section.md b/lambda/latest/dg/example_cloudwatch_GettingStarted_031_section.md
index 73a7bc719..7910f3d9a 100644
--- a//lambda/latest/dg/example_cloudwatch_GettingStarted_031_section.md
+++ b//lambda/latest/dg/example_cloudwatch_GettingStarted_031_section.md
@@ -38,2 +38,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Set up logging
-    LOG_FILE="cloudwatch-dashboard-script.log"
+    # Set up logging with secure permissions
+    LOG_FILE="${HOME}/.cloudwatch-dashboard-script.log"
+    touch "$LOG_FILE" && chmod 600 "$LOG_FILE"
@@ -43,0 +45,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Security: Set strict error handling
+    set -euo pipefail
+    trap 'handle_error "Script failed at line $LINENO"' ERR
+    
@@ -46 +51,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        echo "ERROR: $1"
+        local error_msg="${1:-Unknown error}"
+        echo "ERROR: $error_msg" >&2
@@ -53,2 +59 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        echo "An error occurred. Do you want to clean up the created resources? (y/n): "
-        read -r CLEANUP_CHOICE
+        echo "An error occurred. Proceeding with automatic cleanup..."
@@ -56 +60,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [[ "${CLEANUP_CHOICE,,}" == "y" ]]; then
@@ -58,4 +62,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            aws cloudwatch delete-dashboards --dashboard-names LambdaMetricsDashboard
-            echo "Cleanup complete."
-        else
-            echo "Resources were not cleaned up. You can manually delete them later."
+        aws cloudwatch delete-dashboards --dashboard-names LambdaMetricsDashboard 2>/dev/null || true
+        
+        # Clean up temporary files
+        if [ -n "${TEMP_DIR:-}" ] && [ -d "$TEMP_DIR" ]; then
+            rm -rf "$TEMP_DIR"
@@ -62,0 +68,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        rm -f dashboard-body.json
+        
+        echo "Cleanup complete."
@@ -65,0 +74,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Security: Validate AWS CLI is installed
+    if ! command -v aws &> /dev/null; then
+        handle_error "AWS CLI is not installed. Please install it and try again."
+    fi
+    
@@ -68,2 +81 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    aws sts get-caller-identity > /dev/null 2>&1
-    if [ $? -ne 0 ]; then
+    if ! aws sts get-caller-identity > /dev/null 2>&1; then
@@ -73,2 +85,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Get the current region
-    REGION=$(aws configure get region)
+    # Get the current region securely
+    REGION=$(aws configure get region 2>/dev/null || echo "")
@@ -80,0 +93,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Validate region format
+    if ! [[ "$REGION" =~ ^[a-z]{2}-[a-z]+-[0-9]{1}$ ]]; then
+        handle_error "Invalid AWS region format: $REGION"
+    fi
+    
@@ -83 +100,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    LAMBDA_FUNCTIONS=$(aws lambda list-functions --query "Functions[*].FunctionName" --output text)
+    LAMBDA_FUNCTIONS=$(aws lambda list-functions --region "$REGION" --query "Functions[*].FunctionName" --output text 2>/dev/null || echo "")
+    
@@ -87 +105 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Create a temporary directory for Lambda function code
+        # Create a temporary directory for Lambda function code with secure permissions
@@ -88,0 +107,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        chmod 700 "$TEMP_DIR"
+        trap 'rm -rf "$TEMP_DIR"' EXIT
@@ -91 +111 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        cat > "$TEMP_DIR/index.js" << EOF
+        cat > "$TEMP_DIR/index.js" << 'EOF'
@@ -102,2 +122,11 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        cd "$TEMP_DIR" || handle_error "Failed to change to temporary directory"
-        zip -q function.zip index.js
+        if ! cd "$TEMP_DIR"; then
+            handle_error "Failed to change to temporary directory"
+        fi
+        
+        if ! zip -q function.zip index.js; then
+            handle_error "Failed to create zip file"
+        fi
+        
+        # Create a role for the Lambda function with restricted trust policy
+        ROLE_NAME="LambdaDashboardTestRole-$(date +%s)"
+        TRUST_POLICY='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
@@ -105,3 +134 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Create a role for the Lambda function
-        ROLE_NAME="LambdaDashboardTestRole"
-        ROLE_ARN=$(aws iam create-role \
+        if ! ROLE_ARN=$(aws iam create-role \
@@ -109 +136 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}' \
+            --assume-role-policy-document "$TRUST_POLICY" \
@@ -111,3 +138 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            --output text)
-        
-        if [ $? -ne 0 ]; then
+            --output text 2>/dev/null); then
@@ -121 +146 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        aws iam attach-role-policy \
+        if ! aws iam attach-role-policy \
@@ -123,4 +148,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
-        
-        if [ $? -ne 0 ]; then
-            aws iam delete-role --role-name "$ROLE_NAME"
+            --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"; then
+            aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true
@@ -131,2 +154,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        FUNCTION_NAME="DashboardTestFunction"
-        aws lambda create-function \
+        FUNCTION_NAME="DashboardTestFunction-$(date +%s)"
+        if ! aws lambda create-function \
@@ -137,3 +160,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            --zip-file fileb://function.zip
-        
-        if [ $? -ne 0 ]; then
+            --zip-file fileb://function.zip \
+            --region "$REGION" > /dev/null 2>&1; then
@@ -142,2 +164,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
-            aws iam delete-role --role-name "$ROLE_NAME"
+                --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true
+            aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true
@@ -150 +172 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            aws lambda invoke --function-name "$FUNCTION_NAME" --payload '{}' /dev/null > /dev/null
+            aws lambda invoke --function-name "$FUNCTION_NAME" --payload '{}' /dev/null --region "$REGION" > /dev/null 2>&1 || true
@@ -154 +176 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Clean up temporary directory
+        # Go back to original directory
@@ -156 +177,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        rm -rf "$TEMP_DIR"
@@ -163,0 +185,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        FUNCTION_NAME=""
+        ROLE_NAME=""
@@ -169,2 +192,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create a JSON file for the dashboard body
-    cat > dashboard-body.json << EOF
+    # Create a JSON file for the dashboard body with secure permissions
+    DASHBOARD_JSON="dashboard-body-$$.json"
+    touch "$DASHBOARD_JSON" && chmod 600 "$DASHBOARD_JSON"
+    
+    # Escape special characters in region and function name for JSON
+    REGION_ESCAPED=$(printf '%s\n' "$REGION" | sed 's:[\/&]:\\&:g')
+    FUNCTION_ESCAPED=$(printf '%s\n' "$DEFAULT_FUNCTION" | sed 's:[\/&]:\\&:g')
+    
+    cat > "$DASHBOARD_JSON" << EOF
@@ -187 +217 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "region": "$REGION",
+            "region": "$REGION_ESCAPED",
@@ -204 +234 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "region": "$REGION",
+            "region": "$REGION_ESCAPED",
@@ -221 +251 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "region": "$REGION",
+            "region": "$REGION_ESCAPED",
@@ -237,2 +267,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-              "value": "$DEFAULT_FUNCTION",
-              "label": "$DEFAULT_FUNCTION"
+              "value": "$FUNCTION_ESCAPED",
+              "label": "$FUNCTION_ESCAPED"
@@ -246,3 +276,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create the dashboard using the JSON file
-    DASHBOARD_RESULT=$(aws cloudwatch put-dashboard --dashboard-name LambdaMetricsDashboard --dashboard-body file://dashboard-body.json)
-    DASHBOARD_EXIT_CODE=$?
+    # Validate JSON before sending
+    if ! jq empty "$DASHBOARD_JSON" 2>/dev/null; then
+        handle_error "Invalid JSON generated for dashboard"
+    fi
@@ -250,2 +281,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Check if there was a fatal error
-    if [ $DASHBOARD_EXIT_CODE -ne 0 ]; then
+    # Create the dashboard using the JSON file
+    if ! DASHBOARD_RESULT=$(aws cloudwatch put-dashboard \
+        --dashboard-name "LambdaMetricsDashboard-$(date +%s)" \
+        --dashboard-body file://"$DASHBOARD_JSON" \
+        --region "$REGION" 2>&1); then
@@ -254 +288 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            aws lambda delete-function --function-name "$FUNCTION_NAME"
+            aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null || true
@@ -257,2 +291,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
-            aws iam delete-role --role-name "$ROLE_NAME"
+                --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true
+            aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true
@@ -264 +298 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    if [[ "$DASHBOARD_RESULT" == *"DashboardValidationMessages"* ]]; then
+    if echo "$DASHBOARD_RESULT" | grep -q "DashboardValidationMessages"; then
@@ -271,0 +306,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Extract dashboard name from result
+    DASHBOARD_NAME=$(echo "$DASHBOARD_RESULT" | grep -oP '"DashboardName"\s*:\s*"\K[^"]+' || echo "LambdaMetricsDashboard")
+    
@@ -274,4 +311 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    DASHBOARD_INFO=$(aws cloudwatch get-dashboard --dashboard-name LambdaMetricsDashboard)
-    DASHBOARD_INFO_EXIT_CODE=$?
-    
-    if [ $DASHBOARD_INFO_EXIT_CODE -ne 0 ]; then
+    if ! DASHBOARD_INFO=$(aws cloudwatch get-dashboard --dashboard-name "$DASHBOARD_NAME" --region "$REGION" 2>&1); then