Serverless computing removed the server from the security conversation, but it didn't remove the risk — it just relocated it into IAM policies, event triggers, and the dependency tree bundled inside every function's deployment package. AWS Lambda alone caps functions at 900 seconds of execution and a 250MB unzipped deployment package, yet within that small footprint teams routinely ship node_modules directories with dozens of transitive dependencies, broad IAM roles copied from tutorials, and plaintext secrets in environment variables. When CVE-2021-44228 (Log4Shell) landed in December 2021, teams running Java-based Lambda functions with log4j bundled in their layers had no SBOM to tell them which functions were affected — some spent over three weeks manually auditing deployment packages. This guide covers ten concrete practices for securing AWS Lambda, Azure Functions, and Google Cloud Functions, organized around the questions security teams actually ask when they inherit a serverless estate.
What Makes Serverless Security Different From Traditional Cloud Security?
Serverless security differs because you no longer control the OS, host, or network perimeter — you're securing code, IAM permissions, and event triggers instead of servers and firewalls. There's no persistent instance to install a host-based agent on, no long-running process to attach a traditional EDR sensor to, and cold starts mean a function's entire lifecycle can be under 200 milliseconds. PureSec's original Serverless Top 10 (2018), later folded into OWASP's Serverless guidance, identified categories like SAS-1 (function event-data injection) and SAS-5 (over-privileged function permissions) precisely because these risks don't map to CVE-style host vulnerabilities. Practice 1: inventory every function, its trigger sources, and its IAM role before you write a single security control — you can't secure what you haven't enumerated, and most teams discover 20-30% more live functions than their deployment records show.
How Do You Prevent Over-Privileged Lambda Functions?
You prevent over-privileged functions by scoping each function's execution role to the exact actions and resource ARNs it needs, never to a managed policy like AWSLambdaFullAccess. Practice 2: replace wildcard resource ARNs ("Resource": "*") with explicit ARNs — a function that reads one DynamoDB table should have dynamodb:GetItem on that table's ARN, not dynamodb:* on every table in the account. Practice 3: run IAM Access Analyzer's policy generation against 90 days of CloudTrail activity to identify unused permissions on existing roles; in most audits, functions use fewer than half the permissions granted to them. Practice 4: separate roles per function rather than sharing one role across a service — a single compromised function with a shared role gives an attacker lateral access to every resource that role touches, turning one vulnerable dependency into an account-wide incident.
How Do You Secure Dependencies Packaged Inside Serverless Functions?
You secure serverless dependencies by generating a software bill of materials (SBOM) for every deployment package and scanning it before the function ships, not after. Practice 5: scan at build time against your CI pipeline rather than relying on periodic account-wide scans — a function's node_modules or Python site-packages directory is frozen at deploy time, so a vulnerability introduced today can sit live in production for months if scanning only runs weekly. Practice 6: track transitive dependencies specifically; Log4Shell's blast radius was so large precisely because log4j was rarely a direct dependency — it arrived nested three or four layers deep inside logging frameworks, and teams without SBOM visibility couldn't answer "are we affected?" for days. Snyk's 2023 State of Cloud Native Security research found that container and serverless workloads carry a materially higher share of unpatched high-severity CVEs than traditional VM fleets, largely because ephemeral deployment artifacts get rebuilt and redeployed without a corresponding re-scan step.
How Do You Protect Serverless Functions From Event-Data Injection?
You protect against event-data injection by treating every event source — API Gateway payloads, S3 object metadata, SQS message bodies, DynamoDB streams — as untrusted input requiring validation, exactly like an HTTP request body. Practice 7: validate and sanitize event data at the top of function handlers before it reaches any downstream call, since a Lambda function invoked by an S3 PUT event will happily pass an attacker-controlled filename straight into a shell command or SQL query if the handler doesn't check it first. Practice 8: lock down API Gateway resource policies and enable request validation models so malformed or oversized payloads get rejected at the gateway layer instead of reaching function code at all. Because serverless functions are frequently daisy-chained (API Gateway to Lambda to SQS to another Lambda), a single unvalidated field can propagate through three or four hops before it's ever logged, making injection bugs in serverless architectures harder to trace than in a monolith.
How Do You Manage Secrets and Monitor Threats in Ephemeral Functions?
You manage secrets by pulling them from AWS Secrets Manager or Parameter Store with KMS encryption at invocation time, never by hardcoding them in environment variables, which are visible in plaintext to anyone with lambda:GetFunctionConfiguration permissions on the console or CLI. Practice 9: rotate any secret stored in environment variables and migrate to a secrets manager with automatic rotation — a Lambda function's environment variables are also included in CloudFormation templates and Terraform state files by default, which means a leaked IaC repo can leak production credentials too. Practice 10: instrument runtime monitoring using the Lambda Extensions API or equivalent telemetry hooks in Azure and GCP, since CloudTrail alone only logs the invocation event, not what the function did during execution — and with average Lambda cold starts under a second, a traditional agent-based detection tool often finishes attaching after the malicious code has already run and the container has been recycled.
How Safeguard Helps
Safeguard maps every serverless dependency to an SBOM automatically at build time, then runs reachability analysis to determine whether a vulnerable package — like a transitive log4j or lodash dependency — is actually invoked in a function's code path, cutting through the noise of CVEs that scanners flag but attackers can't reach. Griffin, Safeguard's AI-powered triage engine, prioritizes findings by exploitability and blast radius across your Lambda, Azure Functions, and Cloud Functions estate, factoring in the over-privileged IAM roles and public event triggers that turn a low-severity CVE into a critical one. When a fix is available, Safeguard opens an auto-fix pull request with the dependency bump pre-tested against your build, so teams aren't manually chasing patch cycles the way many did during Log4Shell. Safeguard also ingests existing SBOMs from your CI/CD pipeline for organizations that already generate them, unifying serverless, container, and traditional application risk into a single reachability-scored view.