
Serverless changes what you attack. There is no server to port-scan, no OS to exploit, no long-lived host to pivot through. A function spins up, runs your code with an IAM role, and disappears. That collapses the attack surface down to four things: the function code, the events that trigger it, the permissions it carries, and the dependencies it ships with. Get those right and serverless is genuinely hard to break; get them wrong and a single event injection inherits an over-privileged role straight into your account.
This guide covers serverless penetration testing for AWS Lambda, Azure Functions, and Google Cloud Functions: event injection across the many trigger sources, over-privileged execution roles, dependency and secrets risk, and a methodology that fits short-lived, event-driven code. The OWASP Serverless Top 10 anchors the framework.
Serverless penetration testing assesses the security of functions-as-a-service applications (AWS Lambda, Azure Functions, Google Cloud Functions) by focusing on code, event sources, IAM permissions, and dependencies rather than infrastructure. The cloud provider owns the runtime, patching, and isolation, so the testable surface shifts almost entirely into the application and its configuration.
The mental model is different from a traditional app. A monolith has a handful of front doors; a serverless app has dozens of functions, each triggered by different event sources, each with its own role. The attack surface is wide and shallow. The OWASP Serverless Top 10 reframes the familiar web risks for this model, and much of it overlaps with API and application testing covered in our web application pentesting checklist.
Event injection is the serverless equivalent of injection attacks, and it is broader because functions accept input from many event sources, not just HTTP. A Lambda can be triggered by API Gateway, an SQS or SNS message, an S3 object-created event, a DynamoDB stream, a SES email, or an IoT message. Each carries attacker-influenceable data, and developers often trust event data they would never trust from a web form.
The bug pattern is the same as classic injection: untrusted event data reaches a dangerous sink without validation. That sink might be a database query (SQLi or NoSQLi), an OS command, a dynamic eval, or a downstream API call. Because non-HTTP triggers feel internal, validation is often skipped entirely. Test every event source, not just the API. The underlying injection logic carries over from our SSRF testing guide and standard injection testing.
Over-privileged execution roles are the highest-impact serverless finding because a compromised function inherits whatever its role can do. When you achieve code execution through an event injection or a vulnerable dependency, you are immediately operating with the function's IAM permissions. If that role carries wildcard actions or broad data access, a single function bug becomes account-wide compromise.
The fix is one role per function, scoped to exactly what that function needs. During testing, enumerate each function's role and model its blast radius: in AWS, read the role policy and run pmapper; in Azure and GCP, check the managed identity or service account bindings. Functions also expose their environment variables to any code that runs in them, so any secret stored there (API keys, database credentials) is readable post-compromise. The IAM escalation paths in our AWS penetration testing guide apply directly to these roles.
Third-party dependencies are a larger risk in serverless than in traditional apps because each function ships with its full dependency tree and runs with the function's permissions. A vulnerable npm or PyPI package pulled into a function can give an attacker code execution, and that code immediately holds the function's IAM role. Run software composition analysis against the deployment package, not just the repo, since build steps can introduce drift.
Secrets are the second issue. Environment variables are convenient but readable by any code in the execution context and sometimes visible in the function configuration to anyone with list permissions. Prefer a secrets manager (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager) with the function granted least-privilege read access at runtime. Also check for the serverless metadata pivot: functions on some platforms can still reach the metadata endpoint to retrieve role credentials, so the SSRF-to-credentials path is not exclusive to VMs.
Use a code-and-config first methodology. Start by mapping every function, its triggers, and its role (the application's serverless.yml, SAM template, or Terraform is gold here). Then for each function: test every event source for injection, enumerate and model the execution role, scan dependencies, and hunt for secrets in environment variables and code.
Tooling combines application and cloud techniques. The OWASP Serverless Top 10 is the framework. Use standard SCA tooling for dependency vulnerabilities, pmapper and the cloud-native IAM tools to model role blast radius, and Prowler or ScoutSuite to catch misconfigured functions and overly permissive resource policies. Because serverless apps deploy constantly and each deploy can introduce a new function or widen a role, this is a natural fit for continuous, agentic pentesting rather than a once-a-year manual pass. Fold the results into your cloud security posture checklist.