aws-lambda-url-public
Function URL with AuthType NONE + public resource policy is internet-invocable.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
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 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) — 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}.'