Lambda Function URL Auth Bypass: None, IAM, and Confused Callers
Lambda function URLs are convenient HTTPS endpoints glued straight to a function. Convenience is how AuthType: NONE ships to production. Your first question is not "is there a Lambda?" It is "who is allowed to call this URL, and did the team think something else was enforcing auth?"
Inventory the URL
Public JS bundles, mobile apps, and Terraform modules often embed https://*.lambda-url.*.on.aws/. Hit OPTIONS and GET with no signature. If you get application JSON instead of an IAM error, you are looking at an unauthenticated invoke surface.
Compare that behavior with the "real" API the docs advertise—API Gateway with a JWT authorizer, or Cognito-protected routes. Dual entry points are common. The Gateway path checks tokens; the function URL does not.
Also grep for FunctionUrlConfig, AWS::Lambda::Url, and CDK addFunctionUrl in public IaC. Staging aliases with chatty names (dev-url, debug) are where NONE hides after prod "went IAM."
AuthType NONE versus IAM
NONE means the resource policy allows public lambda:InvokeFunctionUrl. Anyone who knows the URL can invoke. Severity tracks what the function does: password reset, admin export, internal webhook, or a harmless health check. Read responses and side effects on an account you own.
AWS_IAM means SigV4 is required. That is not the end of testing. Check the resource-based policy for Principal: "*" with a loose condition, or for principals belonging to accounts outside the expected callers. If you already have another role from the program, try InvokeFunctionUrl with those keys. Cross-role access still counts.
Throttle yourself. Function URLs are easy to DoS with enthusiasm; one deliberate canary invoke beats a scanner loop.
Bypass shapes worth trying
- Old function URL left active after traffic moved to Gateway
- Preview or
stagealiases still onNONEwhileproduses IAM - Functions that trust an
Authorizationheader inside code but never verify it when reached via URL - CORS configurations that reveal allowed headers and tempt weak custom auth
- Different qualifyer / alias URLs than the one marketing documents
Do the boring test: strip cookies and tokens entirely. If the business action still runs, write that down in one sentence. Custom header checks that accept Bearer null, empty strings, or undefined as a string show up more than they should.
Event payloads matter. A URL that only accepts POST with a signed body field might still leak stack traces or neighbor tenant errors on malformed GET. Capture those carefully; they sometimes reveal internal ARNs for the next finding.
Proof and fix language
Show the unauthenticated request, the sensitive response or state change on your test tenant, and where the duplicate entry point lives. Recommend deleting unused function URLs, setting AWS_IAM with tight principals, or putting auth back in API Gateway / a proper JWT authorizer shared by every invoke path. Code-level checks are a backup, not the only gate. Rotate any secrets the open function could mint or read.
Function URLs are easy to forget in diagrams. Hunt the URL that never made the architecture slide.