This check flags Lambda functions that run outside a VPC, which means they cannot reach private resources like RDS databases or internal services and bypass your network controls. Fix it by attaching the function to private subnets with a properly scoped security group, but only when the function actually needs private network access.
Most Lambda functions ship without any VPC configuration. That is the default, and for a lot of use cases it is fine. But the moment your function needs to talk to a private database, an internal API, or any resource that should never touch the public internet, running outside a VPC becomes a problem. The lambda_novpc check identifies functions that have no VPC configuration so you can decide, deliberately, whether that is correct.
The nuance here matters. This is not a check that should make you panic and shove every function into a VPC. It is a prompt to review your assumptions about where a function runs and what it can reach.
What this check detects
The lambda_novpc check inspects each Lambda function in your AWS account and reports any function whose VpcConfig is empty. A function without VPC configuration runs in the Lambda service-managed network. It gets outbound internet access through an AWS-managed path, but it has no route to resources inside your own VPCs.
You can confirm a function's VPC status with a single call:
aws lambda get-function-configuration \
--function-name my-function \
--query 'VpcConfig'
If the result is null or an empty object, the function is not in a VPC. A function that is VPC-attached returns subnet IDs, security group IDs, and a VPC ID.
Note: Lambda functions in a VPC connect through Hyperplane elastic network interfaces (ENIs). AWS provisions these once per unique subnet and security group combination, which is why modern VPC-attached Lambdas no longer suffer the cold-start penalty they did before 2019. The ENI sits between your function and your subnet, not inside it.
Why it matters
The risk depends entirely on what the function does. A function with no VPC config falls into one of two buckets, and only one of them is a real finding.
1. The function needs private resources but cannot reach them
If a function is supposed to query an RDS instance, an ElastiCache cluster, or an internal service on a private subnet, and it has no VPC config, it simply cannot connect. Teams sometimes work around this by making the database publicly accessible, which is far worse than the original problem. A public RDS endpoint protected only by a security group is one credential leak away from a breach.
Danger: If you ever find a Lambda outside a VPC talking to a database with PubliclyAccessible: true, treat it as an active exposure. The database is reachable from the internet, and the only thing between an attacker and your data is a security group rule and a password. Fix the network path, then disable public access.
2. The function bypasses your network egress controls
Functions outside a VPC route outbound traffic through the Lambda-managed network. That means they ignore your VPC route tables, NAT gateways, network firewalls, and egress filtering. If your security model assumes all outbound traffic from your account passes through a controlled egress point, a VPC-less function is a blind spot. Data exfiltration from a compromised function would not show up in your VPC flow logs.
3. Compliance frameworks expect network segmentation
PCI DSS, HIPAA, and SOC 2 controls frequently require that workloads handling sensitive data sit inside segmented networks with documented traffic paths. A function processing cardholder data or PHI outside any VPC is hard to defend in an audit, even if it technically works.
Warning: Putting a function in a VPC does not automatically give it internet access. A VPC-attached Lambda in a private subnet loses outbound internet unless you add a NAT gateway or VPC endpoints. If your function calls a third-party API and a public AWS API, moving it into a VPC without planning egress will break it.
How to fix it
First, decide whether the function actually needs VPC access. If it only calls public AWS APIs (S3, DynamoDB, SNS) and external HTTPS endpoints, leaving it out of a VPC is correct and you should mark this as an accepted exception rather than "fixing" it.
If the function does need private resources, attach it to private subnets with a dedicated security group.
Step 1: Identify the right subnets and create a security group
Use private subnets that have a route to a NAT gateway (for internet-bound traffic) or to the VPC endpoints your function needs. Create a security group scoped to this function:
aws ec2 create-security-group \
--group-name lambda-my-function-sg \
--description "Egress for my-function Lambda" \
--vpc-id vpc-0abc123
Lambda only needs outbound rules. Allow egress to the specific resources it talks to, for example a database security group on port 5432:
aws ec2 authorize-security-group-egress \
--group-id sg-0lambda123 \
--protocol tcp --port 5432 \
--source-group sg-0database456
Step 2: Attach the function to the VPC
Warning: Updating VpcConfig triggers a function update that can take a minute or two while ENIs are provisioned. Run this during a maintenance window if the function serves production traffic, and have a rollback ready.
aws lambda update-function-configuration \
--function-name my-function \
--vpc-config SubnetIds=subnet-0aaa,subnet-0bbb,SecurityGroupIds=sg-0lambda123
Use at least two subnets in different Availability Zones so the function survives an AZ outage.
Step 3: Add an egress path if the function needs the internet or AWS APIs
For AWS service calls, prefer VPC endpoints over NAT. They keep traffic on the AWS network and avoid NAT data processing charges. A gateway endpoint for S3 and DynamoDB is free:
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0abc123 \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-0private123
For arbitrary internet access, ensure your private subnets route 0.0.0.0/0 through a NAT gateway.
Step 4: Update the execution role
The function's execution role needs permission to manage ENIs. The AWS managed policy AWSLambdaVPCAccessExecutionRole covers this:
aws iam attach-role-policy \
--role-name my-function-role \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
Terraform example
If you manage Lambda with Terraform, the VPC configuration is a single block:
resource "aws_lambda_function" "my_function" {
function_name = "my-function"
role = aws_iam_role.lambda.arn
handler = "index.handler"
runtime = "nodejs20.x"
filename = "function.zip"
vpc_config {
subnet_ids = [aws_subnet.private_a.id, aws_subnet.private_b.id]
security_group_ids = [aws_security_group.lambda.id]
}
}
Tip: Define a reusable module for VPC-attached Lambdas that bundles the security group, subnet references, and the AWSLambdaVPCAccessExecutionRole attachment. Teams then opt into private networking by calling the module instead of wiring four resources together each time, which kills an entire class of misconfiguration.
How to prevent it from happening again
The goal is not to force every function into a VPC. It is to make the decision explicit and to catch functions that need private access but lack it.
Policy-as-code in CI/CD
Run a policy check on your Terraform plan before apply. With Checkov, the relevant rule is straightforward to wire into a pipeline:
checkov -d . --check CKV_AWS_117
That rule flags Lambda functions without VPC configuration. If most of your functions legitimately run outside a VPC, suppress it globally and instead tag the functions that must be in a VPC, then assert on those.
Tag-driven enforcement
Adopt a convention where functions that handle sensitive data carry a tag like network=private. Write a custom OPA or Conftest policy that fails the build if a function tagged network=private has no vpc_config:
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_lambda_function"
resource.change.after.tags.network == "private"
not resource.change.after.vpc_config
msg := sprintf("Lambda %s is tagged private but has no VPC config", [resource.address])
}
Continuous monitoring
IaC gates only cover resources created through IaC. Functions created in the console or by other teams slip past. Lensix continuously evaluates lambda_novpc across every account, so a function that drifts out of policy or gets created by hand is surfaced without waiting for the next pipeline run.
Best practices
- Decide deliberately. Document whether each function needs private access. Treat "not in a VPC" as a conscious choice, not an oversight.
- Never make a database public to avoid VPC config. Putting the function in the VPC is always the better answer.
- Use VPC endpoints over NAT gateways for AWS services. Lower cost, less latency, and traffic stays on the AWS backbone.
- Scope security groups tightly. A Lambda security group should only allow egress to the exact resources the function touches.
- Span multiple Availability Zones. Always attach to at least two private subnets in different AZs.
- Watch your ENI limits. Heavy VPC-Lambda usage with many subnet and security group combinations consumes ENIs and can hit account limits at scale.
- Keep egress filtered. The whole point of moving into a VPC is to regain network control, so route outbound traffic through your egress inspection rather than wide-open NAT.
Tip: When you migrate a function into a VPC, test cold-start latency and connectivity to every downstream dependency before cutting over production traffic. The most common surprise is a function that worked fine outside the VPC and suddenly times out calling a public API because nobody added a NAT route.

