Skip to content

Lambda functions should restrict public URL

Lambda function URLs with no authentication let anyone on the internet invoke your function by simply hitting the endpoint. This exposes your backend logic, environment variables, and any data the function can access (databases, S3 buckets, internal APIs) to unauthenticated callers. Even if the function itself seems harmless, attackers can use it for reconnaissance or as a pivot point into your VPC.

Unlike API Gateway endpoints, Lambda function URLs have no built-in WAF integration, throttling policies, or request validation. Leaving authorization_type as NONE removes the only access control mechanism the URL offers.

Retrofit consideration

Changing authorization_type from NONE to AWS_IAM on an existing function URL will immediately break any unauthenticated callers. Coordinate with consumers to sign requests with SigV4 before switching.

Implementation

Choose the approach that matches how you manage Terraform.

If you use terraform-aws-modules/lambda/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.

module "lambda" {
  source  = "terraform-aws-modules/lambda/aws"
  version = ">=8.0.0"

  create_package         = false
  function_name          = "abc123"
  handler                = "index.lambda_handler"
  local_existing_package = "lambda_function.zip"
  runtime                = "python3.12"

  authorization_type = "AWS_IAM"
}

Use AWS provider resources directly. See docs for the resources involved: aws_lambda_function_url.

resource "aws_lambda_function" "this" {
  function_name    = "pofix-abc123"
  role             = "arn:aws:iam::123456789012:role/example-role"
  runtime          = "python3.12"
  handler          = "index.handler"
  filename         = "lambda_function.zip"
  source_code_hash = "base64encodedhashabcdef1234567890=="
}

resource "aws_lambda_function_url" "this" {
  function_name = "example-function"

  authorization_type = "AWS_IAM"
}

What this control checks

This control evaluates the aws_lambda_function_url resource. To pass, authorization_type must be set to AWS_IAM. A value of NONE fails the control because it permits unauthenticated invocation from any source. If no aws_lambda_function_url resource exists for a given function, the function has no public URL and passes by default.

When authorization_type is AWS_IAM, callers must sign requests using AWS Signature Version 4. You also need to grant lambda:InvokeFunctionUrl via a resource-based policy (using aws_lambda_permission) or an IAM identity policy for authorized principals. The cors block on aws_lambda_function_url does not affect authorization and should be configured separately based on your browser client requirements.

Common pitfalls

  • Resource-based policy can still allow public invoke

    Even with authorization_type set to AWS_IAM, an aws_lambda_permission resource with principal set to "*" and function_url_auth_type set to "NONE" can re-open public access. Audit your aws_lambda_permission resources alongside the function URL configuration.

  • Function URL created outside Terraform

    Developers can create function URLs via the AWS Console or CLI (aws lambda create-function-url-config) without any Terraform involvement. Use an SCP or Config rule to detect and deny lambda:CreateFunctionUrlConfig calls with AuthType of NONE at the organization level.

  • CORS misconfiguration mistaken for security

    The cors block on aws_lambda_function_url controls browser-enforced cross-origin headers. It does not restrict server-side access. A function URL with authorization_type = "NONE" and restrictive CORS is still fully callable by curl, scripts, or any non-browser HTTP client.

  • Conditional authorization_type in modules

    Shared Terraform modules sometimes default authorization_type to "NONE" for development convenience and accept a variable override. Grep your module source for default = "NONE" and ensure your root module always passes "AWS_IAM" explicitly.

Audit evidence

An auditor expects evidence that no Lambda function URL allows unauthenticated access. Config rule results (from a custom or managed rule evaluating lambda:GetFunctionUrlConfig across all functions) showing each function as compliant are solid artifacts. Console screenshots of each function's "Function URL" configuration panel showing Auth type: AWS_IAM also work.

For programmatic evidence, the output of aws lambda list-function-url-configs --function-name <name> should show "AuthType": "AWS_IAM" for every configured URL. CloudTrail logs for CreateFunctionUrlConfig and UpdateFunctionUrlConfig API calls can demonstrate that no function URL was ever provisioned with NONE authorization, or that any such configuration was promptly remediated.

Framework-specific interpretation

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: lambda_function_restrict_public_url

  • Checkov Check: CKV_AWS_301

  • Powerpipe Control: aws_compliance.control.lambda_function_restrict_public_url

  • Prowler Check: awslambda_function_url_public

  • AWS Security Hub Control: Lambda.1

Last reviewed: 2026-03-09