Back to Checks
aws

VPC endpoint service allows only trusted principals or none

vpc_endpoint_services_allowed_principals_trust_boundaries
Service: vpcSeverity: high
OfficialBuilt-inVerified
Categories:trust-boundaries
Resource Type:AwsEc2VpcEndpointService

VPC endpoint services are assessed for their allowed principals, comparing each to a configured set of trusted accounts and identifying any untrusted principals or a wildcard * present in the allowlist.

Risk

Untrusted or wildcard principals can create PrivateLink connections to your service, eroding segmentation. This enables unauthorized data access (confidentiality), abuse of internal APIs (integrity), and excess load on backends (availability).

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks vpc_endpoint_services_allowed_principals_trust_boundaries

Recommendation

Apply least privilege: restrict allowed principals to vetted account IDs and avoid *. Maintain a central trust registry, enforce separation of duties with approval workflows, and review entries regularly. Use defense in depth with strong service authentication and continuous configuration monitoring.

Remediation

Terraform

# Allow only a trusted principal (delete this resource to allow none)
resource "aws_vpc_endpoint_service_allowed_principal" "<example_resource_name>" {
  service_id    = "<example_resource_id>"
  principal_arn = "arn:aws:iam::<TRUSTED_ACCOUNT_ID>:root"  # CRITICAL: only this trusted account can create endpoints
}

NativeIaC

# Allow only a trusted principal (or attach none to allow no principals)
Resources:
  <example_resource_name>:
    Type: AWS::EC2::VPCEndpointServicePermissions
    Properties:
      ServiceId: <example_resource_id>
      AllowedPrincipals:
        - arn:aws:iam::<TRUSTED_ACCOUNT_ID>:root  # CRITICAL: restricts access to only this trusted account

Other

1Open the AWS VPC console and go to Endpoint services
2Select the endpoint service (<example_resource_id>)
3Open the Allowed principals tab and click Edit allowed principals
4Remove all entries that are not trusted, including any wildcard (*)
5Optionally leave the list empty (no principals) or keep only trusted account IDs/ARNs
6Save changes

Check Code

from re import compile

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.vpc.vpc_client import vpc_client


class vpc_endpoint_services_allowed_principals_trust_boundaries(Check):
    def execute(self):
        findings = []
        # Get trusted account_ids from prowler.config.yaml
        trusted_account_ids = vpc_client.audit_config.get("trusted_account_ids", [])
        for service in vpc_client.vpc_endpoint_services:
            report = Check_Report_AWS(metadata=self.metadata(), resource=service)

            if not service.allowed_principals:
                report.status = "PASS"
                report.status_extended = (
                    f"VPC Endpoint Service {service.id} has no allowed principals."
                )
                findings.append(report)
            else:
                for principal in service.allowed_principals:
                    # Account ID can be an ARN or just a 12-digit string
                    pattern = compile(r"^[0-9]{12}$")
                    match = pattern.match(principal)
                    if not match:
                        account_id = (
                            principal.split(":")[4] if principal != "*" else "*"
                        )
                    else:
                        account_id = match.string

                    if (
                        account_id in trusted_account_ids
                        or account_id in vpc_client.audited_account
                    ):
                        report.status = "PASS"
                        report.status_extended = f"Found trusted account {account_id} in VPC Endpoint Service {service.id}."
                    else:
                        report.status = "FAIL"
                        if account_id == "*":
                            report.status_extended = f"Wildcard principal found in VPC Endpoint Service {service.id}."
                        else:
                            report.status_extended = f"Found untrusted account {account_id} in VPC Endpoint Service {service.id}."
                    findings.append(report)

        return findings