Guide · AWS Inspector · Lambda Scanning
AWS Inspector Lambda Scanning — Package Vulnerabilities, Code Scanning, and Layer Coverage
Inspector Lambda scanning has two distinct modes with separate pricing and separate activation: standard scanning (PACKAGE_VULNERABILITY — $0.30/function/month) detects known CVEs in packages bundled in the function's deployment package and all attached Lambda Layers; code scanning (CODE_VULNERABILITY — additional $0.30/function/month) runs CodeGuru Security SAST analysis on the function's source code to detect injection flaws, cryptographic misuse, and hard-coded credentials. Most MCP server teams should start with standard scanning only — it covers the dependency supply chain without requiring access to source code — and evaluate code scanning separately if SAST is not already handled in CI. Neither scan type requires an agent; Inspector pulls the function package from the control plane without affecting runtime performance or cold start times.
TL;DR
Enable with aws inspector2 enable --resource-types LAMBDA (standard) and optionally LAMBDA_CODE (SAST). Inspector scans on function create/update and rescans on new CVE publication — no agents, no runtime overhead. For Inspector overview see the Inspector overview. For EC2 scanning see the EC2 guide. For ECR scanning see the ECR guide. For finding management see the findings guide.
Standard vs. code scanning
| Feature | Standard scanning (LAMBDA) | Code scanning (LAMBDA_CODE) |
|---|---|---|
| Finding type | PACKAGE_VULNERABILITY | CODE_VULNERABILITY |
| What is analyzed | Package manifests and lock files in the function deployment package and attached layers | Source code in the function deployment package via CodeGuru Security SAST |
| Languages covered | Python, Node.js, Ruby, Java, Go, .NET | Python, Java, JavaScript/TypeScript, C# (CodeGuru supported languages) |
| Cost | $0.30/function/month | $0.30/function/month (additive to standard) |
| Container image functions | Only via ECR enhanced scanning path | Not supported — .zip only |
| Additional service dependency | None | CodeGuru Security must be active in the account |
| Rescan on new CVE | Yes | No — code findings are static; rescan only on function update |
Enabling Lambda scanning
Lambda scanning requires no configuration beyond enabling it in Inspector. Once enabled, all functions in the region are scanned automatically — there is no per-function opt-in or IAM role to attach to the function.
# Enable standard Lambda scanning (package vulnerabilities)
aws inspector2 enable \
--resource-types LAMBDA \
--region us-east-1
# Enable both standard and code scanning
aws inspector2 enable \
--resource-types LAMBDA LAMBDA_CODE \
--region us-east-1
# Verify Lambda scanning is active
aws inspector2 batch-get-account-status \
--account-ids "$(aws sts get-caller-identity --query Account --output text)" \
--query 'accounts[0].resourceState.lambda'
The initial scan of all existing Lambda functions in the region typically completes within minutes for standard scanning. Code scanning may take longer for functions with large deployment packages. After the initial scan, rescans are triggered by function updates (deploy) and by new CVE publications (standard scanning only — code scanning does not rescan unless the function is updated).
Package coverage: what Inspector reads from Lambda functions
Inspector reads the function deployment package (.zip) from the Lambda service — it does not need to invoke the function or access its environment variables. The package manifests Inspector looks for within the .zip:
| Runtime | Files Inspector reads | Common pitfall |
|---|---|---|
| Python | site-packages/*/METADATA, requirements.txt | If packages are installed with --target . instead of --target ./python, the metadata path differs from a standard site-packages layout — Inspector should still detect it, but verify with ListFindings after deploy |
| Node.js | node_modules/*/package.json | Tree-shaken bundles (esbuild, webpack) eliminate node_modules — Inspector cannot scan what was bundled away; you get zero findings, which is both good (smaller attack surface) and a gap (can't confirm CVE-free) |
| Java | pom.xml, fat JAR manifests | Uber-JARs shaded with Maven Shade plugin — Inspector extracts nested JARs; shading that renames packages breaks CVE matching |
| Ruby | gems/ directory, Gemfile.lock | Lambda layers used for gems must have the standard gems/ directory structure |
| Go | Binary GOPATH metadata embedded in compiled binary | Go binaries compiled with -ldflags="-w -s" strip debug info — Inspector may not detect Go module versions |
The bundled-dependency gap is the most common issue for modern Node.js MCP servers using esbuild or webpack: your node_modules is compiled away into a single bundle, so Inspector sees no npm packages to scan. This is actually a security benefit (reduced attack surface), but you need a separate tool in CI (e.g., Snyk, npm audit, Grype) to verify your dependencies before bundling.
Lambda Layer scanning
When a Lambda function has layers attached, Inspector scans the packages in all attached layers as part of the function scan — the function and its layers are analyzed together, and findings reference the specific layer or function package where the vulnerable package was found.
# View findings that originated in a Lambda Layer vs the function package
aws inspector2 list-findings \
--filter-criteria '{
"lambdaFunctionName": [{"comparison":"EQUALS","value":"my-mcp-handler"}],
"findingType": [{"comparison":"EQUALS","value":"PACKAGE_VULNERABILITY"}]
}' \
--query 'findings[].{Score:inspectorScore,CVE:packageVulnerabilityDetails.vulnerabilityId,Package:packageVulnerabilityDetails.vulnerablePackages[0].name,LayerArn:packageVulnerabilityDetails.vulnerablePackages[0].sourceLayerArn}' \
--output table
The sourceLayerArn field distinguishes layer-origin findings from function-package findings. If the vulnerable package is in a shared layer used by many functions, fixing the layer version (update to the patched layer ARN and deploy all functions that reference it) resolves the finding for all affected functions simultaneously.
If you use the AWS SDK for Python (boto3) layer or similar AWS-managed layers, Inspector will report package vulnerabilities in those layers too. AWS-managed layers are updated by AWS; you do not control the layer version. For unresolved CVEs in AWS-managed layers, create a suppression rule — AWS will update the layer on their schedule. For customer-managed layers, you are responsible for the update.
Code scanning (SAST via CodeGuru Security)
Lambda code scanning runs CodeGuru Security SAST analysis on the function's source code within the deployment package. It detects:
- Injection vulnerabilities: SQL injection, OS command injection, LDAP injection in function code
- Cryptographic misuse: use of weak algorithms (MD5, SHA1 for security purposes, DES, RC4), hardcoded IV, ECB mode
- Hard-coded credentials: AWS access keys, passwords, API tokens embedded in source code
- Path traversal: unsanitized user input used in file path operations
- Exposure of sensitive data: logging of sensitive variables, HTTP response header injection
# View code vulnerability findings for a Lambda function
aws inspector2 list-findings \
--filter-criteria '{
"lambdaFunctionName": [{"comparison":"EQUALS","value":"my-mcp-handler"}],
"findingType": [{"comparison":"EQUALS","value":"CODE_VULNERABILITY"}]
}' \
--query 'findings[].{Score:inspectorScore,Title:title,File:codeVulnerabilityDetails.filePath.fileName,Line:codeVulnerabilityDetails.filePath.startLine,Type:codeVulnerabilityDetails.cweIds[0]}' \
--output table
Code scanning findings include the file name and line number of the vulnerable code within the deployment package. For MCP servers handling tool call inputs from LLM agents, injection detection is particularly relevant — any code path that constructs SQL queries or shell commands from tool call arguments is a high-value target for code scanning.
Code scanning does not rescan unless the function is updated — it is a point-in-time SAST check, not a continuous monitor. New findings only appear when you deploy a new function version. This is different from standard package scanning, which can produce new findings on unchanged deployed functions when CVEs are published.
Rescan triggers for Lambda
| Trigger | Standard scanning | Code scanning |
|---|---|---|
| Function created or updated (new deploy) | Yes — within minutes | Yes — within 15 minutes |
| New CVE published matching installed package | Yes — automatic, no deploy needed | No — code findings are static |
| Layer version updated on function | Yes — layer packages re-scanned | Yes — if code references changed |
| Inspector initially enabled in account | Yes — initial scan of all functions | Yes — initial SAST of all .zip functions |
The practical implication: a Lambda function that was deployed months ago and has not been updated can accumulate new PACKAGE_VULNERABILITY findings as new CVEs are published against its bundled dependencies. Schedule regular function deployments (even no-op deploys) as part of your security cadence if you have long-lived Lambda functions — this also triggers a fresh code scan confirming no new CODE_VULNERABILITY findings were introduced.
Container image Lambda functions
Lambda functions deployed as container images (using --package-type Image) are not scanned by the Lambda scanning path. They are scanned via the ECR enhanced scanning path when the image is pushed to ECR — enabling --resource-types LAMBDA does not provide coverage for image-based functions. Enable --resource-types ECR and switch the ECR repository to enhanced scanning to cover image-based Lambda functions.
# Verify which of your Lambda functions are .zip vs image-based
aws lambda list-functions \
--query 'Functions[].{Name:FunctionName,PackageType:PackageType,Runtime:Runtime}' \
--output table
# For image-based functions, check ECR coverage
aws inspector2 list-coverage \
--filter-criteria '{"resourceType":[{"comparison":"EQUALS","value":"AWS_ECR_CONTAINER_IMAGE"}]}' \
--query 'coveredResources[?contains(resourceId, `lambda`)].{Id:resourceId,Status:scanStatus.statusCode}' \
--output table
Failure modes reference
| Failure | Symptom | Fix |
|---|---|---|
| Zero findings for Node.js functions | Inspector enabled, function deployed, no PACKAGE_VULNERABILITY findings | Function uses a bundled build (esbuild/webpack) — node_modules not in package; use CI-side dependency scanning instead; Inspector finding zero is accurate |
| No CODE_VULNERABILITY findings despite LAMBDA_CODE enabled | Code scanning enabled but no SAST findings appear | CodeGuru Security must also be active; container-image functions not supported; only Python/Java/JS/TS/C# analyzed; function code may be minified/compiled (not raw source) |
| Layer findings not attributed to specific layer | sourceLayerArn is null in findings | Package is in the function package itself, not a layer — the field is only populated for layer-origin packages |
| Findings persist after patching a package | Updated package version in requirements.txt but finding still ACTIVE | Deploy a new function version to trigger rescan; Inspector scans the deployed package, not the source repository |
| Image Lambda INACTIVE in Lambda coverage | ListCoverage shows image-based function as INACTIVE | Expected — image functions are covered via ECR path, not Lambda path; check ECR coverage for the function's image URI |