aws-lambda-url-public

Function URL with AuthType NONE + public resource policy is internet-invocable.

derived aws emits ExposedToInternet

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'function': None} ExecutesAs {'role': None}

where

node_type(?function) == ServerlessFunction function has a FunctionUrlConfig with AuthType == NONE resource-based policy allows lambda:InvokeFunctionUrl for Principal '*' with lambda:FunctionUrlAuthType == NONE resource-based policy ALSO allows lambda:InvokeFunction for Principal '*' (typically gated by lambda:InvokedViaFunctionUrl == true) — required for URLs created on/after Oct 2025

emit

target typeAnonymousIdentity
source?function
target<AnonymousIdentity>
permissionslambda:InvokeFunctionUrl lambda:InvokeFunction
conditionsresource_policy
state logicif resource policy grants BOTH lambda:InvokeFunctionUrl AND lambda:InvokeFunction to Principal '*': ACTIVE; elif only lambda:InvokeFunctionUrl is granted: CONDITIONAL(resource_policy) — a pre-Oct-2025 URL may still be public, but a post-Oct-2025 URL returns 403 without the InvokeFunction grant

Narrative

{function.name} is invocable from the public internet via a function URL (AuthType NONE + public resource policy), running as {role.name}.

Raw rule rules/derived/aws/lambda.yaml

id: aws-lambda-url-public
emits: ExposedToInternet
description: Function URL with AuthType NONE + public resource policy is internet-invocable.
match:
- - function: null
  - ExecutesAs
  - role: null
where:
- node_type(?function) == ServerlessFunction
- function has a FunctionUrlConfig with AuthType == NONE
- resource-based policy allows lambda:InvokeFunctionUrl for Principal '*' with lambda:FunctionUrlAuthType
  == NONE
- "resource-based policy ALSO allows lambda:InvokeFunction for Principal '*' (typically gated by lambda:InvokedViaFunctionUrl\
  \ == true) \u2014 required for URLs created on/after Oct 2025"
emit:
  target_type: AnonymousIdentity
  source: ?function
  target: <AnonymousIdentity>
  permissions:
  - lambda:InvokeFunctionUrl
  - lambda:InvokeFunction
  conditions:
  - resource_policy
  state_logic: "if resource policy grants BOTH lambda:InvokeFunctionUrl AND lambda:InvokeFunction to Principal\
    \ '*': ACTIVE; elif only lambda:InvokeFunctionUrl is granted: CONDITIONAL(resource_policy) \u2014\
    \ a pre-Oct-2025 URL may still be public, but a post-Oct-2025 URL returns 403 without the InvokeFunction\
    \ grant"
  false_positive_note: "AuthType AWS_IAM is NOT public \u2014 only NONE plus wildcard-principal policy\
    \ statements are. As of October 2025 a NONE-auth function URL requires the resource-based policy to\
    \ grant BOTH lambda:InvokeFunctionUrl AND lambda:InvokeFunction to Principal '*' (the latter usually\
    \ scoped by the lambda:InvokedViaFunctionUrl condition); URLs created before Oct 2025 may be public\
    \ with only lambda:InvokeFunctionUrl. Without the lambda:InvokeFunction grant, a post-Oct-2025 URL\
    \ returns 403 and is NOT internet-invocable -> downgrade to CONDITIONAL/POTENTIAL rather than ACTIVE.\
    \ An SCP forcing lambda:FunctionUrlAuthType==AWS_IAM makes this BLOCKED. Do not emit for functions\
    \ with only an AWS_IAM URL."
  narrative: '{function.name} is invocable from the public internet via a function URL (AuthType NONE
    + public resource policy), running as {role.name}.'
move · open · esc close