There is a persistent misconception that serverless functions are inherently more secure than containers or VMs. The logic goes: no server to manage means no server to compromise. This is dangerously wrong.
AWS Lambda functions carry the same software supply chain risks as any other application. They have dependencies, they run on runtimes with their own vulnerabilities, and they integrate with third-party services that can be compromised. The difference is that serverless environments make these risks harder to see.
The Hidden Attack Surface
A typical Lambda function is a small amount of application code sitting on top of a large stack of things you did not write and probably have not audited.
The runtime. Your function runs on a managed runtime -- Node.js, Python, Java, Go, Ruby, .NET. Each runtime ships with its own set of libraries. When a vulnerability is found in the Node.js HTTP parser or the Python urllib library, every function using that runtime version is affected.
AWS patches runtimes, but not instantly. There is always a window between public CVE disclosure and runtime update. During that window, your functions are vulnerable.
Dependencies. A Node.js Lambda with a package.json might pull in hundreds of transitive dependencies. Each one is code written by someone you do not know, maintained with varying levels of attention, and downloaded from a public registry that has been targeted by dependency confusion attacks repeatedly.
Lambda layers. Layers are shared code packages that multiple functions can reference. They are a supply chain risk multiplier -- a compromised layer affects every function that uses it. And unlike dependencies in your package.json, layers can be managed by different teams or even third parties.
Custom runtimes. If you use a custom runtime, you own the entire runtime supply chain. That includes the runtime binary, its dependencies, and all system libraries bundled with it.
Dependency Confusion in Serverless
Dependency confusion attacks are particularly dangerous for Lambda functions because of how deployment packages are typically built.
The attack works like this: an attacker discovers the name of an internal package your organization uses (often through leaked package.json files, job postings, or error messages). They publish a malicious package with the same name but a higher version number to the public npm or PyPI registry. When your build system resolves dependencies, it picks the higher version number from the public registry instead of your internal one.
Why Lambda is especially vulnerable: Many teams build Lambda deployment packages on developer laptops or in CI environments without strict registry configuration. The build environment might not be configured to prioritize private registries, and there is no admission controller or scanning gate between the build and the deployment.
Mitigations:
- Use scoped packages on npm (
@yourorg/package-name) to prevent naming collisions with public packages. - Configure pip to use
--index-urlpointing to your private PyPI mirror exclusively. - Use CodeArtifact or Artifactory as a proxy that gives priority to internal packages.
- Verify dependency integrity using lock files with hashes.
Layer Security
Lambda layers are shared dependencies that can be published publicly or within your AWS organization. They are powerful and risky.
Audit third-party layers. If you use layers published by third parties, you are trusting their code to run inside your function with all its permissions. Review the layer contents before using them. Download the layer, extract it, and inspect what is inside.
Version-pin layers. Always reference layers by version number, not just ARN. Layer versions are immutable -- once published, a specific version cannot be changed. But if you reference a layer without a version, you might get a newer version that you have not audited.
Scan layer contents. Run vulnerability scanning on your layers just like you would on a container image. Layers contain packages that have CVEs, and those CVEs do not go away just because the code is in a layer instead of a Dockerfile.
Minimize layer usage. Every layer you add is another supply chain dependency. If you can include the code directly in your function's deployment package, do that instead. Layers should be used when sharing code across many functions justifies the additional supply chain risk.
Runtime Vulnerabilities
AWS manages the Lambda runtime, but you manage which runtime version your function uses.
Do not use deprecated runtimes. AWS regularly deprecates older runtime versions. Functions on deprecated runtimes do not receive security patches. If you are still running Node.js 12 or Python 3.6 functions, you are running on unpatched software.
Monitor AWS runtime updates. Subscribe to the AWS Lambda runtime release notes. When a new runtime version patches a security vulnerability, update your functions promptly.
Test runtime updates. Do not blindly update runtime versions. Test your functions on the new runtime before deploying to production. Runtime updates can change behavior in subtle ways that break your code.
Consider managed runtimes over custom runtimes. Managed runtimes are patched by AWS. Custom runtimes are patched by you. Unless you have a specific requirement for a custom runtime, use a managed one.
Deployment Package Security
Your Lambda deployment package is the artifact that contains your function code and dependencies. Securing it is essential.
Build in a clean environment. Do not build deployment packages on developer laptops where the environment might be contaminated. Use CI/CD with a clean, ephemeral build environment.
Pin all dependency versions. Use exact version pinning in your package.json, requirements.txt, or equivalent. Use lock files and verify their integrity. Never deploy with floating version ranges.
Minimize the package size. Every byte in your deployment package is code that could contain vulnerabilities. Use tree shaking, remove unused dependencies, and exclude development-only packages from the deployment bundle.
Generate SBOMs for deployment packages. Run Syft or Trivy against your deployment zip file to generate an SBOM before uploading it to Lambda. Store the SBOM alongside the function version for traceability.
IAM and Permission Risks
Lambda's execution role defines what the function can do in your AWS environment. Overly permissive roles amplify the impact of any supply chain compromise.
Apply least privilege. Every Lambda function should have its own execution role with only the permissions it needs. A function that reads from one DynamoDB table should not have dynamodb:* on *.
Avoid wildcard permissions. "Resource": "*" in a Lambda execution role means that a compromised dependency can access every resource of that type in your account. Scope resources to specific ARNs.
Review permissions regularly. Use IAM Access Analyzer to identify unused permissions in your Lambda execution roles. Remove permissions that are not being used.
Monitoring and Detection
Detecting supply chain compromises in Lambda functions requires monitoring at multiple levels.
Enable CloudTrail for Lambda API calls. Track function creation, updates, and invocations. An unexpected function update could indicate a compromised CI/CD pipeline.
Monitor function behavior. Use CloudWatch Logs Insights to detect unusual patterns in your function logs -- unexpected outbound network calls, error spikes, or processing time anomalies.
Use Lambda Insights for resource monitoring. Unusual memory or CPU usage patterns can indicate that a compromised dependency is performing cryptomining or data exfiltration.
Set up GuardDuty for Lambda. GuardDuty can detect compromised Lambda functions based on network activity patterns, including communication with known malicious IP addresses.
How Safeguard.sh Helps
Safeguard.sh brings the same supply chain security rigor to serverless that most organizations only apply to containers. It scans Lambda deployment packages and layers for vulnerabilities, generates SBOMs for every function version, and monitors for newly disclosed CVEs that affect your deployed functions.
The platform gives you visibility into your entire serverless supply chain -- which dependencies are used across which functions, which layers are shared, and which functions are running on deprecated runtimes. When a vulnerability is disclosed in a popular npm package, Safeguard.sh tells you immediately which Lambda functions are affected and what version they need to update to.