Back to Checks
gcp

Cloud Function is not publicly invocable

cloudfunction_function_not_publicly_accessible
Service: cloudfunctionSeverity: high
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:cloudfunctions.googleapis.com/Function

Cloud Functions deny invocation to allUsers and allAuthenticatedUsers, so only explicitly authorized identities or services can trigger them.

The evaluation reviews each function's IAM policy bindings to confirm no public principals are granted invoker access.

Risk

Publicly invocable Cloud Functions expose business logic to the internet and let any caller trigger execution. This enables unauthorized data access when the function returns sensitive output, code execution in shared environments, and denial-of-wallet attacks driven by uncontrolled invocation costs.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler gcp --checks cloudfunction_function_not_publicly_accessible

Recommendation

Apply least privilege to Cloud Function invocation: grant roles/cloudfunctions.invoker only to specific service accounts or groups.

For externally exposed functions, front them with API Gateway or Cloud Endpoints that enforce authentication and rate limiting.

Remediation

CLI

gcloud functions remove-iam-policy-binding <FUNCTION_NAME> --region=<REGION> --member=<allUsers|allAuthenticatedUsers> --role=roles/cloudfunctions.invoker

Terraform

resource "google_cloudfunctions2_function_iam_binding" "<example_resource_name>" {
  project        = "<example_resource_id>"
  location       = "<example_resource_id>"
  cloud_function = "<example_resource_name>"
  role           = "roles/cloudfunctions.invoker"
  members        = ["serviceAccount:<example_resource_id>"] # Critical: never include allUsers or allAuthenticatedUsers
}

Other

1In Google Cloud Console, go to Cloud Functions
2Select the function and open the Permissions tab
3Remove any binding with allUsers or allAuthenticatedUsers
4Grant invocation rights only to specific service accounts or user groups

Check Code

from prowler.lib.check.models import Check, Check_Report_GCP
from prowler.providers.gcp.services.cloudfunction.cloudfunction_client import (
    cloudfunction_client,
)


class cloudfunction_function_not_publicly_accessible(Check):
    """Check that Cloud Functions do not grant invocation rights to all users.

    Verifies that no active Cloud Function has an IAM binding granting access
    to `allUsers` or `allAuthenticatedUsers`. Non-`ACTIVE` functions are
    skipped because their IAM bindings are transient.
    """

    def execute(self) -> list[Check_Report_GCP]:
        """Execute the public-access check across all Cloud Functions.

        Returns:
            A list of `Check_Report_GCP` findings, one per active Cloud
            Function. Status is `FAIL` when the function is invokable by
            `allUsers` or `allAuthenticatedUsers` and `PASS` otherwise.
        """
        findings = []
        for function in cloudfunction_client.functions:
            if function.state != "ACTIVE":
                continue
            report = Check_Report_GCP(
                metadata=self.metadata(),
                resource=function,
                resource_id=function.name,
            )
            if function.publicly_accessible:
                report.status = "FAIL"
                report.status_extended = (
                    f"Cloud Function {function.name} is publicly invocable "
                    f"(allUsers or allAuthenticatedUsers IAM binding detected)."
                )
            else:
                report.status = "PASS"
                report.status_extended = (
                    f"Cloud Function {function.name} is not publicly accessible."
                )
            findings.append(report)
        return findings