Back to blog
AWSCloud SecurityCompute & ContainersKubernetesNetworking

EKS Public Endpoint Open to All CIDRs: Why It Matters and How to Fix It

Learn why an EKS API endpoint open to 0.0.0.0/0 is a risk, how to restrict it with allowed CIDRs or private access, and how to prevent it with policy as code.

TL;DR

This check flags EKS clusters whose public Kubernetes API endpoint accepts connections from 0.0.0.0/0, meaning anyone on the internet can reach it. Restrict access by setting publicAccessCidrs to your known IP ranges, or disable public access entirely and use private endpoints with a bastion or VPN.

The Kubernetes API server is the front door to your entire cluster. Every kubectl command, every controller, every CI/CD deploy talks to it. When you run EKS, AWS manages that API server for you and gives you an endpoint to reach it. The problem flagged by eks_publiccidr is simple: that endpoint is exposed to the public internet with no IP restrictions at all.

An open endpoint does not mean an open cluster. The API server still requires authentication. But leaving it reachable from every IP on earth is a needless expansion of your attack surface, and it removes a cheap, effective layer of defense that costs nothing to enable.


What this check detects

Lensix inspects the endpoint access configuration of each EKS cluster and raises eks_publiccidr when both of these are true:

  • The cluster's public endpoint is enabled (endpointPublicAccess: true).
  • The list of allowed public CIDRs contains 0.0.0.0/0, which permits every IPv4 address.

You can see this configuration yourself with the AWS CLI:

aws eks describe-cluster \
  --name my-cluster \
  --query 'cluster.resourcesVpcConfig.{public:endpointPublicAccess,private:endpointPrivateAccess,cidrs:publicAccessCidrs}'

A flagged cluster returns something like this:

{
  "public": true,
  "private": false,
  "cidrs": [
    "0.0.0.0/0"
  ]
}

Note: EKS supports three endpoint modes. Public only exposes the API to the internet. Public and private exposes it both ways, with traffic from within the VPC staying inside AWS. Private only means the API is reachable only from inside the VPC or connected networks. The publicAccessCidrs field applies whenever public access is on.


Why it matters

The API server authenticates requests, so an open endpoint is not the same as an unauthenticated one. The risk is what that exposure enables when something else goes wrong.

It widens the blast radius of leaked credentials

EKS authentication leans on IAM and the cluster's RBAC. If an attacker obtains a valid kubeconfig, a leaked IAM access key with EKS permissions, or a token from a compromised CI runner, an internet-reachable endpoint means they can use those credentials from anywhere. Lock the endpoint to your corporate egress IPs and a stolen credential becomes far less useful, because the attacker also has to be on your network.

It exposes you to API server vulnerabilities and zero-days

Authentication and authorization bugs in Kubernetes do happen. When a CVE drops that lets an unauthenticated request bypass a control, the clusters that get exploited first are the ones reachable from the open internet. A CIDR restriction buys you time to patch instead of racing attackers.

It invites brute force, scanning, and denial of service

Public EKS endpoints are continuously scanned. Bots probe for misconfigured anonymous access, weak webhook authenticators, and known exploit paths. Even when those attempts fail, they generate noise, consume API server capacity, and can be used to fingerprint your Kubernetes version.

Warning: A common and dangerous combination is an open public endpoint plus an over-permissive aws-auth mapping or a misconfigured system:anonymous binding. The endpoint restriction is your safety net for exactly these mistakes. Do not rely on it alone, but do not throw it away either.

Compliance impact

CIS Kubernetes and CIS EKS benchmarks both call for restricting access to the API server. Frameworks like SOC 2, PCI DSS, and HIPAA expect network controls around administrative interfaces. An EKS endpoint open to 0.0.0.0/0 is a finding auditors will flag.


How to fix it

You have two good options depending on how your teams reach the cluster. Pick the one that matches your access model.

Option 1: Restrict the public endpoint to known CIDRs

If engineers and tooling reach the API from predictable IPs (a NAT gateway, a VPN egress, a corporate office range), keep public access on but scope it.

First, collect the CIDRs that legitimately need access. Common sources include your VPN egress IP, your office IP ranges, and the public IP of any CI/CD runners.

aws eks update-cluster-config \
  --name my-cluster \
  --resources-vpc-config \
    endpointPublicAccess=true,publicAccessCidrs="203.0.113.10/32,198.51.100.0/24"

Warning: If you restrict the CIDRs to a range that does not include your own current IP, you will lock yourself out of the API. Confirm your egress IP first with curl -s https://checkip.amazonaws.com and make sure it is in the list. The update applies within a couple of minutes.

Option 2: Disable public access and use the private endpoint

The stronger posture is to turn off public access entirely and reach the API from inside your network. This keeps API traffic on AWS infrastructure and removes internet exposure completely.

Danger: Disabling the public endpoint will cut off any kubectl access, GitOps controller, or pipeline that connects from outside the VPC. Before you run this, make sure you have a path into the private endpoint: a VPN, AWS Site-to-Site VPN, a bastion host in the VPC, or peered networking. Test that path first.

aws eks update-cluster-config \
  --name my-cluster \
  --resources-vpc-config \
    endpointPublicAccess=false,endpointPrivateAccess=true

To reach a private-only endpoint, connect through a host inside the VPC (or a connected network) and run your usual commands:

aws eks update-kubeconfig --name my-cluster --region us-east-1
kubectl get nodes

Verify the fix

aws eks describe-cluster \
  --name my-cluster \
  --query 'cluster.resourcesVpcConfig.publicAccessCidrs'

The output should list your scoped ranges and no longer contain 0.0.0.0/0:

[
  "203.0.113.10/32",
  "198.51.100.0/24"
]

Fix it as code

If you manage EKS with infrastructure as code, fix the configuration at the source so it does not drift back. Here is Terraform using the AWS provider:

resource "aws_eks_cluster" "this" {
  name     = "my-cluster"
  role_arn = aws_iam_role.cluster.arn

  vpc_config {
    subnet_ids              = var.subnet_ids
    endpoint_public_access  = true
    endpoint_private_access = true

    public_access_cidrs = [
      "203.0.113.10/32",
      "198.51.100.0/24",
    ]
  }
}

With the popular terraform-aws-modules/eks module, the equivalent inputs are:

module "eks" {
  source  = "terraform-aws-modules/eks/aws"

  cluster_name                         = "my-cluster"
  cluster_endpoint_public_access       = true
  cluster_endpoint_private_access      = true
  cluster_endpoint_public_access_cidrs = [
    "203.0.113.10/32",
    "198.51.100.0/24",
  ]
}

Tip: Reference a single Terraform variable or data source for your allowed CIDRs and reuse it across every cluster. When your VPN egress IP changes, you update one place and re-apply, instead of hunting through cluster definitions.


How to prevent it from happening again

Fixing one cluster is easy. Stopping the misconfiguration from reappearing across teams and accounts is the real win.

Block it in CI with policy as code

If you use OPA or Conftest against Terraform plans, write a rule that rejects open CIDRs. Here is a Rego example for a Terraform plan in JSON:

package eks.endpoint

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_eks_cluster"
  cidrs := resource.change.after.vpc_config[_].public_access_cidrs
  cidrs[_] == "0.0.0.0/0"
  msg := sprintf("EKS cluster %q exposes its public endpoint to 0.0.0.0/0", [resource.address])
}

Run it as a required check before any terraform apply:

terraform show -json plan.tfplan > plan.json
conftest test plan.json --policy ./policy

Detect drift continuously

Plan checks only catch changes made through your pipeline. People still click around in the console and run one-off CLI commands. Continuous scanning catches what slips past the pipeline. This is exactly what the Lensix eks_publiccidr check does: it evaluates every cluster across your accounts on a schedule and alerts when a public endpoint opens up to all CIDRs, including changes made outside IaC.

Tip: Pair the plan-time gate with the runtime scan. The gate stops the obvious mistakes before they ship, and the scan catches console edits, emergency changes, and anything created before you adopted the policy.

Use a Service Control Policy as a backstop

SCPs cannot inspect the CIDR list directly, but you can prevent EKS endpoint changes outside of an approved role, forcing all modifications through your reviewed pipeline. Combined with the plan-time check, this closes the manual-edit path at the organization level.


Best practices

  • Prefer private endpoints for production clusters. Reach them through a VPN or bastion. Reserve public access for clusters where private connectivity is genuinely impractical.
  • If you keep public access, always scope the CIDRs to the smallest set of ranges that work. A static NAT gateway IP or VPN egress is ideal because it gives you one stable address to allow.
  • Do not treat the CIDR restriction as your only control. Tighten the aws-auth ConfigMap (or EKS access entries), enforce least-privilege RBAC, and audit for any anonymous bindings.
  • Enable EKS control plane audit logs so you can see who is hitting the API and from where. Ship them to CloudWatch and alert on unexpected source IPs.
  • Review endpoint configuration during every cluster creation. The EKS console defaults to public access, so a cluster spun up quickly often inherits the open posture by accident.

Note: EKS audit logging is not on by default. Enable it with aws eks update-cluster-config --name my-cluster --logging '{"clusterLogging":[{"types":["audit","authenticator"],"enabled":true}]}'. Audit logs incur CloudWatch ingestion and storage costs, so set a retention policy that fits your budget.

The fix here is small and the payoff is real. Scoping the EKS API endpoint to known networks removes a whole class of opportunistic attacks and turns a leaked credential from an immediate breach into a contained one. Make it the default for every cluster, gate it in CI, and scan for drift so it stays that way.