AWS Security ChangesHomeSearch

AWS code-library high security documentation change

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

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

Summary

Enhanced security practices in AWS CLI examples including input validation, secure credential handling, error handling, and resource cleanup. Added Lambda function security improvements like input sanitization and logging.

Security assessment

The changes address security weaknesses by adding input validation to prevent injection attacks, sanitizing user input in Lambda functions, implementing secure credential handling, and adding resource validation. Specific evidence includes: 1) Input sanitization in Lambda (greeter.replace) to prevent code injection, 2) Secure temporary file cleanup (shred), 3) IAM policy improvements for least privilege, 4) IMDSv2 enforcement to mitigate SSRF risks.

Diff

diff --git a/code-library/latest/ug/bash_2_sts_code_examples.md b/code-library/latest/ug/bash_2_sts_code_examples.md
index a4e83dce3..d49d315ad 100644
--- a//code-library/latest/ug/bash_2_sts_code_examples.md
+++ b//code-library/latest/ug/bash_2_sts_code_examples.md
@@ -735 +735 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        read -r CLEANUP_CHOICE
+        CLEANUP_CHOICE="y"
@@ -843,0 +844,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    set -euo pipefail
+    
@@ -855,0 +858,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Validate inputs
+    if [[ -z "$ACCOUNT_ID" ]] || [[ -z "$REGION" ]]; then
+        echo "Error: Failed to retrieve AWS account information" >&2
+        exit 1
+    fi
+    
@@ -858 +866 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create Lambda function code
+    # Create Lambda function code with input validation
@@ -860,0 +869 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    import logging
@@ -862,4 +871,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    def lambda_handler(event, context):
-        print(event)
-        
-        greeter = 'World'
+    logger = logging.getLogger()
+    logger.setLevel(logging.INFO)
@@ -866,0 +874 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    def lambda_handler(event, context):
@@ -868,5 +876 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            if (event['queryStringParameters']) and (event['queryStringParameters']['greeter']) and (
-                    event['queryStringParameters']['greeter'] is not None):
-                greeter = event['queryStringParameters']['greeter']
-        except KeyError:
-            print('No greeter')
+            logger.info("Received event: %s", json.dumps(event))
@@ -874,6 +878 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        try:
-            if (event['multiValueHeaders']) and (event['multiValueHeaders']['greeter']) and (
-                    event['multiValueHeaders']['greeter'] is not None):
-                greeter = " and ".join(event['multiValueHeaders']['greeter'])
-        except KeyError:
-            print('No greeter')
+            greeter = 'World'
@@ -880,0 +880,24 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+            # Safely retrieve greeter from query string parameters
+            query_params = event.get('queryStringParameters') or {}
+            if isinstance(query_params, dict) and 'greeter' in query_params:
+                greeter_value = query_params.get('greeter')
+                if isinstance(greeter_value, str) and greeter_value:
+                    greeter = greeter_value
+            
+            # Safely retrieve greeter from multi-value headers
+            multi_headers = event.get('multiValueHeaders') or {}
+            if isinstance(multi_headers, dict) and 'greeter' in multi_headers:
+                greeter_list = multi_headers.get('greeter', [])
+                if isinstance(greeter_list, list) and greeter_list:
+                    greeter = " and ".join(str(g) for g in greeter_list if g)
+            
+            # Safely retrieve greeter from headers
+            headers = event.get('headers') or {}
+            if isinstance(headers, dict) and 'greeter' in headers:
+                greeter_value = headers.get('greeter')
+                if isinstance(greeter_value, str) and greeter_value:
+                    greeter = greeter_value
+            
+            # Safely retrieve greeter from body
+            body = event.get('body')
+            if body and isinstance(body, str):
@@ -882,15 +905,12 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            if (event['headers']) and (event['headers']['greeter']) and (
-                    event['headers']['greeter'] is not None):
-                greeter = event['headers']['greeter']
-        except KeyError:
-            print('No greeter')
-        
-        if (event['body']) and (event['body'] is not None):
-            body = json.loads(event['body'])
-            try:
-                if (body['greeter']) and (body['greeter'] is not None):
-                    greeter = body['greeter']
-            except KeyError:
-                print('No greeter')
-        
-        res = {
+                    body_dict = json.loads(body)
+                    if isinstance(body_dict, dict) and 'greeter' in body_dict:
+                        greeter_value = body_dict.get('greeter')
+                        if isinstance(greeter_value, str) and greeter_value:
+                            greeter = greeter_value
+                except (json.JSONDecodeError, ValueError) as e:
+                    logger.warning("Failed to parse body: %s", str(e))
+            
+            # Sanitize greeter to prevent injection
+            greeter = greeter.replace('"', '\\"').replace("'", "\\'")
+            
+            response = {
@@ -899 +919 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                "Content-Type": "*/*"
+                    "Content-Type": "application/json"
@@ -901 +921 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "body": "Hello, " + greeter + "!"
+                "body": json.dumps({"message": f"Hello, {greeter}!"})
@@ -904 +924,12 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        return res
+            logger.info("Response: %s", json.dumps(response))
+            return response
+            
+        except Exception as e:
+            logger.error("Unexpected error: %s", str(e), exc_info=True)
+            return {
+                "statusCode": 500,
+                "headers": {
+                    "Content-Type": "application/json"
+                },
+                "body": json.dumps({"error": "Internal server error"})
+            }
@@ -908 +939,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    zip function.zip lambda_function.py
+    zip -q function.zip lambda_function.py || {
+        echo "Error: Failed to create function.zip" >&2
+        exit 1
+    }
@@ -928 +962 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create IAM role
+    # Create IAM role with error handling
@@ -931 +965,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --assume-role-policy-document file://trust-policy.json
+        --assume-role-policy-document file://trust-policy.json \
+        --description "Temporary role for Lambda execution" || {
+        echo "Error: Failed to create IAM role" >&2
+        exit 1
+    }
@@ -936 +974,4 @@ 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"
+        --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" || {
+        echo "Error: Failed to attach IAM policy" >&2
+        exit 1
+    }
@@ -943 +984 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create Lambda function
+    # Create Lambda function with Python 3.11 (more recent runtime)
@@ -946 +987 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --runtime python3.9 \
+        --runtime python3.11 \
@@ -949 +990,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --zip-file fileb://function.zip
+        --zip-file fileb://function.zip \
+        --timeout 30 \
+        --memory-size 128 \
+        --environment "Variables={LOG_LEVEL=INFO}" || {
+        echo "Error: Failed to create Lambda function" >&2
+        exit 1
+    }
@@ -953,2 +1000,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create REST API
-    aws apigateway create-rest-api \
+    # Create REST API with minimum logging
+    API_RESPONSE=$(aws apigateway create-rest-api \
@@ -956 +1003,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --endpoint-configuration types=REGIONAL
+        --endpoint-configuration types=REGIONAL \
+        --description "API for Lambda proxy integration tutorial" \
+        --output json)
@@ -958,2 +1007,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Get API ID
-    API_ID=$(aws apigateway get-rest-apis --query "items[?name=='$API_NAME'].id" --output text)
+    API_ID=$(echo "$API_RESPONSE" | grep -o '"id": "[^"]*"' | head -1 | cut -d'"' -f4)
+    
+    if [[ -z "$API_ID" ]]; then
+        echo "Error: Failed to create API Gateway" >&2
+        exit 1
+    fi
@@ -968 +1021,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --path-part helloworld
+        --path-part helloworld || {
+        echo "Error: Failed to create resource" >&2
+        exit 1
+    }
@@ -973 +1029 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create ANY method
+    # Create ANY method with no authorization (intentional for tutorial)
@@ -978 +1034,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --authorization-type NONE
+        --authorization-type NONE || {
+        echo "Error: Failed to create method" >&2
+        exit 1
+    }
@@ -989 +1048,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --uri "$LAMBDA_URI"
+        --uri "$LAMBDA_URI" || {
+        echo "Error: Failed to create integration" >&2
+        exit 1
+    }
@@ -991,0 +1054 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    STATEMENT_ID="apigateway-invoke-$(openssl rand -hex 4)"
@@ -996 +1059 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --statement-id "apigateway-invoke-$(openssl rand -hex 4)" \