Serverless security: lock down functions and roles
Serverless security means treating every function as a small program with its own permissions, inputs and secrets. Platforms such as AWS Lambda, Azure Functions and Google Cloud Functions run short-lived functions that wake up on an event. The OWASP Serverless / FaaS Security Cheat Sheet says this model brings its own risks compared to traditional servers. This guide turns that sheet into a checklist your team can run, with one worked example.
What serverless security covers
You do not patch a server, but you still own what the function can do and what it will accept. The OWASP sheet lists seven key risks:
- Over-permissioned functions, such as broad roles and
*policies. - Unvalidated event inputs from an API gateway, a storage bucket, a message queue or an IoT device.
- Cold start data leakage, such as state that persists between runs.
- Function chaining abuse, where one compromised function calls others.
- Shared environment risks, such as leftover files in
/tmp. - Hardcoded secrets in code or platform settings.
- Excessive network access.
The rest of this post goes through them in the order you can fix them. If you only have an hour, do the first section.
Give each function its own least-privilege role
The sheet's first rule is least privilege: give each function the minimum permissions it needs. It asks for a role per function and warns against shared high-privilege roles. It also says to scope database and API keys to the smallest set of actions.
Its bad example is a policy that allows every action on every resource. Its good example allows two actions, reading and writing an item, on one named table. The gap between those two is how far an attacker can reach after finding one bug in your code.

A worked example
This function is made up, to show the steps. Say you have a function called send-receipt that reads one order and sends an email. Walk through it like this:
- List what it does: read an order, send one message.
- Write a role with only those two permissions, each tied to the one table and the one sender it uses.
- Remove any permission the function does not use, then run it and see what fails.
- Add back only what a real error says is missing.
- Give the next function its own role. Do not reuse this one.
Now if send-receipt has a flaw, the attacker can read orders and send mail. They cannot touch payments or other tables, because the role does not allow it.
Cut network access and separate sensitive functions
The sheet says to disable default network access unless the function needs it, such as outbound internet access. It suggests private subnets with controlled egress. Egress means traffic going out of your network.
It also asks you to isolate sensitive functions, with payment and sign-in as its examples, from general-purpose ones. And it says to keep production and staging apart with strict boundaries. In practice, ask of each function: does it need to reach the internet at all? If not, close that door. If your team also uses network zones outside serverless, the post on network segmentation covers the same idea for servers.
Check who can call the function
A function has no open port, but it still has triggers. The sheet says to enforce authentication and authorization on all of them, including API Gateway, Pub/Sub, S3 and IoT triggers. A trigger with no check is a door anyone can knock on.
For one function calling another, it says to validate the call with signed tokens or workload identities. This blocks function chaining abuse: a compromised function cannot simply invoke the others. It also says to apply rate limiting and throttling to reduce denial of service and abuse. For the rate side, see the post on login rate limiting.
Treat every event as untrusted input
The sheet is direct: treat all event payloads as untrusted. Validate length, type and format. Protect against common injection attacks, and it names SQL injection, XSS, JSON injection and deserialization. It also says to strip fields and metadata you do not need before you process the event.
The event does not have to come from a web form to be hostile. A storage event carries a file name that a user chose. A queue message may carry text a customer typed. So run the same checks you would on a public endpoint. The post on input validation shows how to build those checks.
The sheet's own example is a small handler that parses the body, checks that the email field looks like an email and returns a 400 error if it does not. Keep that shape: check first, process after.
Keep secrets and state out of the runtime
Do not assume the runtime is clean between runs. The sheet says to avoid storing secrets or temporary sensitive data in global or static variables, and warns about timing differences and leftover files in /tmp. For sensitive work, it says to use single-use execution environments where the platform supports them.
For secrets, it says to fetch them at runtime from a vault or a caching extension, not from function settings such as Lambda environment variables. It also asks for short-lived credentials and automatic rotation. Never hardcode a secret in code or config. The post on secrets management goes into the full life of a key.
Log events and sign what you deploy
The sheet asks for centralized logging, with CloudWatch, Azure Monitor and GCP Logging as examples, and for masking secrets and personal data in those logs. Its example replaces any field with "password" in its name with stars before logging.
For supply chain, it says to scan dependencies, keep deployment packages minimal, and sign packages so the publisher can be verified. It adds that a checksum alone does not prove who published a package. For AWS Lambda it names code signing, with UntrustedArtifactOnDeployment set to Enforce. The default, Warn, lets through deployments that fail the checks, and layers must be signed too. The post on dependency updates covers the scanning half.
Here is the checklist to copy:
- Each function has its own role, with no
*actions. - Network access is off unless a function needs it.
- Every trigger requires authentication and authorization.
- Every event is validated and trimmed.
- Secrets come from a vault at runtime, not from settings or globals.
- Logs are central and masked.
- Packages are scanned, minimal and signed.
Frequently asked questions
Is serverless more secure than a server I run myself?
The platform takes some work off you, but the OWASP sheet says the model brings its own risks. Your roles, inputs, secrets and packages are still yours to secure.
What should I fix first in a serverless app?
Fix the roles. The sheet lists over-permissioned functions first among its risks, and a scoped role limits the damage from every other bug.
Are environment variables a safe place for secrets?
The sheet says to fetch secrets at runtime from a vault or caching extension instead of function settings like Lambda environment variables.
Does a checksum prove my package is genuine?
No. The sheet says a checksum alone does not authenticate the publisher. Sign packages and verify the signature before you deploy.
Get started
Building something that has to be safe? Book a meeting with whitehatstoic: tell us the product, the deadline and your biggest worry, and we reply with a plan and a price. We test web apps and AI systems and give you a written report with fixes and a retest after the fixes.
Comments
No comments yet.
Sign in or make an account to comment.