Dev.to Security 🔐 Cybersecurity 👁 0 📖 2 min read

We use VPC endpoints for S3, are we compliant? VPC endpoint without a policy is a wormhole to every S3 bucket

✓ Human-authored analysis; AI used for formatting and proofreading. One of the confident statements on r/aws: "We route all S3 traffic through a VPC endpoint, so our data stays on the private network." VPC endpoints do

✓ Human-authored analysis; AI used for formatting and proofreading.

One of the confident statements on r/aws: "We route all S3 traffic through a VPC endpoint, so our data stays on the private network." VPC endpoints do keep traffic off the public internet. But the confidence creates a blind spot.

The Default Policy Problem

When you create a VPC gateway endpoint for S3, AWS attaches a default policy:

{
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "*",
      "Resource": "*"
    }
  ]
}

Any principal on the VPC can reach ANY S3 bucket in ANY AWS account. Not just your buckets or buckets in your account. Any bucket, anywhere, that allows access from the calling principal.

The endpoint restricts the network path but not the destination. A compromised EC2 instance on your VPC can exfiltrate data to an attacker-controlled S3 bucket in a different account, and the traffic never touches the internet. Your VPC flow logs show "private network." Your data is in someone else's bucket.

The HIPAA Citation

HIPAA section 164.312(e)(1) requires transmission security. The technical measures to guard against unauthorized access to electronic PHI during transmission. A VPC endpoint that allows unrestricted destination access doesn't satisfy this. It secures the transport but not the authorization of where data can flow.

How Stave Detects It

Stave evaluates this as a compound risk using two controls:

Control What it checks Result
CTL.S3.NETWORK.VPC.001 VPC endpoint or IP condition exists PASS
CTL.S3.NETWORK.POLICY.001 Endpoint policy restricts access FAIL

The compound finding is the dangerous one. CTL.S3.NETWORK.VPC.001 passes — yes, you have a VPC endpoint. But CTL.S3.NETWORK.POLICY.001 fails. The endpoint policy is missing or uses the default full-access policy. Together, this creates a false sense of security: the VPC endpoint exists, but it's a wormhole to the entire S3 namespace.

stave evaluate \
  --controls controls/s3/network/ \
  --observations observations/ \
  --eval-time 2026-04-08T00:00:00Z
Security State: NON_COMPLIANT

Findings:
  phi-vpc-endpoint:
    CTL.S3.NETWORK.POLICY.001  UNSAFE  VPC endpoint policy unrestricted
      VPC endpoint policy is missing or uses the default full-access
      policy. Any principal on the VPC can reach any S3 bucket.

      Remediation: Replace the default endpoint policy with one that
      restricts Resource to specific bucket ARNs and Action to required
      S3 operations only.

The fix is to replace the default policy with a restrictive one:

{
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject", "s3:PutObject"],
      "Resource": [
        "arn:aws:s3:::phi-data-bucket/*",
        "arn:aws:s3:::phi-logs-bucket/*"
      ]
    }
  ]
}

A VPC endpoint without an endpoint policy is security theater. It looks compliant where the traffic stays on the private network, the checkbox is checked. But the default Allow * policy turns the endpoint into an unrestricted gateway to every S3 bucket in existence. Stave detects when the endpoint exists but the policy doesn't restrict it, surfacing the compound risk that a single-control scanner would miss.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.