I'm building a small Rust Lambda function that fetches my GitHub statistics and returns an SVG image, which I want to embed directly in a README. The Function URL immediately responds with {"Message":"Forbidden"}.
I confirmed that the URL configuration uses AuthType NONE, and the Lambda resource policy allows Principal * to perform lambda:InvokeFunctionUrl when the Function URL authentication type is NONE. I'm still unable to access the endpoint publicly. Is there another required permission or account setting I'm missing?
3 Answers
Lambda Function URLs can be accessed from the public Internet, so API Gateway or CloudFront is not inherently required just to make the URL reachable. If the URL still returns 403, focus first on the Lambda permissions and confirm that both required actions are present for the correct function and alias or version.
Even if you get the endpoint working, an unauthenticated URL that performs work on every request can be risky. Anyone could repeatedly call it, consume Lambda invocations, or cause excessive GitHub API requests and rate limiting.
Since the result is an image that probably doesn’t need to be generated every second, consider running the Lambda on a schedule and storing the generated SVG in S3. CloudFront can then serve and cache the file publicly. That is cheaper, more resilient, and avoids exposing an expensive operation directly.
For a public Lambda Function URL, the permissions need to cover both actions: lambda:InvokeFunctionUrl and lambda:InvokeFunction. Checking only the URL-specific permission can still result in a 403. Add a public permission for lambda:InvokeFunction, for example:
aws lambda add-permission --function-name YOUR_FUNCTION_NAME --statement-id AllowPublicInvoke --action lambda:InvokeFunction --principal "*"
Then wait briefly for the policy change to propagate and test the URL again. There isn’t necessarily a hidden account-wide block involved; the usual issue is that one half of the required permission setup is missing.
The Lambda documentation describes both permissions as required for a public Function URL, so granting only lambda:InvokeFunctionUrl is not sufficient.

Adding rate limiting, such as through AWS WAF, would provide another layer of protection if the function remains publicly callable.