The serverless model, also known as FaaS (Function as a Service), has become the backbone of many production architectures. AWS Lambda, Azure Functions and GCP Cloud Functions today run everything from public APIs to critical data pipelines, payment integrations and AI workflows. The team writes the function, the provider handles servers, operating system and scaling. That same abstraction reshapes the attack surface and the pentest methodology.
Auditing serverless is not the same as replicating a container pentest or a generic cloud pentest. The attacker stops fighting against open ports and starts fighting against IAM policies, malformed events, dependency layers and effective cross-account permissions. This guide covers why serverless requires a different approach, which vectors appear repeatedly, what tooling to use and how to harden functions on AWS, Azure and GCP in 2026.
The essentials: in serverless the host surface disappears and the event plus IAM plus dependency surface emerges. If the pentest does not cover event validation, role granularity, layer supply chain and function URL exposure, the report leaves out 80% of the real risk.
Why serverless requires a different pentest
The difference from containers or VMs comes down to three structural properties.
The first one is short-lived functions. A Lambda lives only for the time required to process an event, milliseconds to a few minutes. There is no persistent EDR agent, no local log that survives and no way to log into the machine to investigate later. Telemetry is externalized in real time or it does not exist.
The second is the event-driven nature. The function is triggered by heterogeneous events: object uploaded to S3, message on SQS, mutation on DynamoDB Streams, API Gateway call, Cosmos DB trigger, Pub/Sub push. Each source brings its own schema and pitfalls. An attacker who controls any of those sources partially controls the input.
The third one is that the model is IAM heavy. The function needs an execution role with permissions over the rest of the estate. All the privilege logic that used to live in system accounts, sudoers and firewalls has shifted to JSON policies. A single misplaced wildcard turns an innocuous function into a vector for full account takeover.
On top of that, observability is typically poorer, because functions are written by product teams and instrumentation ends up as a second-order task.
OWASP Serverless Top 10
The formal reference is still the OWASP Serverless Top 10 published in 2017, conceptually valid today. The original categories (injection, broken authentication, sensitive data exposure, XXE, broken access control, security misconfiguration, XSS, insecure deserialization, components with known vulnerabilities and insufficient logging) are reinterpreted on serverless: injection becomes event injection, components with vulnerabilities become dependencies and layers, access control becomes misconfigured IAM.
OWASP also maintains the Serverless Goat, a deliberately vulnerable Lambda application useful for training red and blue teams. Complement the Top 10 with the CSA Serverless Application Security Top 10 and with AWS Well-Architected Serverless Lens and Azure Serverless Security best practices.
Specific serverless pentest vectors
Event data injection
The attacker manipulates the event triggering the function. If the function processes an S3 object name without sanitizing and passes it to os.system() or to a SQL query, RCE or injection happens without touching the API. Typical points: filenames in S3 events, attributes in SQS messages, JSON payloads in API Gateway without schema validation, fields in DynamoDB Streams. Any event field is untrusted input.
Function with over-privileged IAM role
The most recurring flaw. The function needs to write to a DynamoDB table and gets assigned dynamodb:* over Resource: *. The day it is compromised, the attacker has access to every table in the account. Multiplied across dozens of functions, the result is a lateral privilege network that an attacker with a single entry point traverses all the way up to admin.
Lambda layers supply chain poisoning
Layers share code across functions. If a layer maintained by a third party or a compromised internal account is updated with malicious code, every consuming function inherits the change on the next cold invocation. The attacker does not need to touch your account, it is enough to publish a new version of a layer that your account imports by public ARN.
Vulnerable dependencies (NPM, PyPI in layers)
Lambda Node.js drags NPM modules, Python drags PyPI, .NET drags NuGet. Unpatched CVEs execute inside the function context with its associated IAM role. Rotation tends to be worse than on containers because there is no regularly rebuilt base image.
Cold start side-channels
Cold start is the first invocation after inactivity or version change, involving provisioning a new container, loading runtime, importing dependencies and running initialization. Researchers have demonstrated side-channels where the pattern reveals internal behavior or where an attacker invoking repeatedly infers when provisioning occurs. Rarely a primary vector but it appears in serious reports when sensitive data is processed.
Cross-account assume role abuse
Lambda and Cloud Functions can assume roles in other accounts via sts:AssumeRole or equivalents. If the trust policy of the destination role accepts a lax condition, a compromised function in account A pivots to account B. Multi-account pivots surprise clients because their controls are designed per account, not for the effective federation.
Hardcoded secrets in environment variables
Environment variable holding the database connection string, a third-party API key or a Slack token. Lambda and Azure Functions env vars are readable by any identity with lambda:GetFunctionConfiguration or equivalent, and they show up in logs when an exception prints the context. The correct pattern is Secrets Manager, Azure Key Vault or GCP Secret Manager with granular permissions and in-memory cache.
Resource exhaustion and cost runaway
A serverless function charges per invocation and duration. An attacker triggering massive invocations, for example by pushing millions of messages to the consumed queue, generates a five or six figure bill in hours. The "denial of wallet" attack. Controls: budget alarms, throttling per function, concurrency limits and origin validation at the trigger.
Tooling for serverless pentest
Pacu is the reference AWS exploitation framework with modules to enumerate Lambda, dump env vars, download function code and detect vulnerable roles. CloudGoat and Serverless Goat are intentionally vulnerable environments to practice and validate custom tooling.
Lambda Probe performs reconnaissance against functions exposed via Function URLs or API Gateway, runtime fingerprinting and enumeration of timeout and memory. Snyk and Checkov scan source code and IaC configuration (Terraform, Serverless Framework, SAM, CDK) detecting vulnerable dependencies and excessive permissions. cloudsplaining analyzes IAM policies. Custom Python scripts with boto3, azure-identity and google-cloud-functions complement when client logic is atypical.
On blue team, Falco with serverless plugins, AWS GuardDuty with Lambda detection and Azure Defender for App Service cover runtime detection.
AWS Lambda specifics
The Lambda pentest revolves around three axes. The first one is the execution role: we audit policy by policy with iam:SimulatePrincipalPolicy, identifying wildcards and excessive permissions. The recommended practice is one role per function with minimal permissions to the specific resource.
The second is VPC config. A Lambda outside VPC has Internet access by default and cannot reach private resources. Inside VPC, it reaches private resources but loses Internet unless a NAT Gateway is configured. In VPC the function can be a pivot to internal databases; outside, it can exfiltrate without network restriction.
The third is exposure via Function URLs. Since 2022 a Lambda can have a public HTTPS endpoint without API Gateway. Many appear with AuthType: NONE, accessible without authentication. Auditing them requires enumerating lambda:GetFunctionUrlConfig and validating CORS and authentication.
Complementary checks: dead letter queues, misused provisioned concurrency that keeps warm containers holding secrets in memory, and CloudWatch Logs configuration with adequate retention and restricted read permissions.
Azure Functions
The first item is the identity model: managed identity versus connection strings. The correct practice is System-assigned or User-assigned Managed Identity with granular RBAC over consumed resources. What actually appears is connection strings with secrets in local.settings.json versioned in Git or in Application Settings with no expiration.
The second is the hosting model: Consumption Plan, Premium Plan and App Service Plan. Consumption scales automatically and shares infrastructure with other tenants. Premium guarantees warm instances and VNet networking. App Service Plan runs on dedicated instances. Consumption is susceptible to cold start side-channels and denial of wallet via massive scaling; App Service Plan inherits the full App Service surface and demands template hardening.
Additional aspects: function keys (master, function, host) that act as invocation secrets if Entra ID is not used, integration with Application Insights for telemetry, and Networking with Service Endpoints or Private Endpoints depending on the plan.
GCP Cloud Functions
The first axis is service account scoping. By default, a Cloud Function gen1 runs with the App Engine service account, which holds Editor over the project. Every function in a project shares a role with broad permissions unless explicitly configured. Auditing GCP starts by listing functions and verifying each runs with its own service account scoped to the minimum required resource.
The second is IAM bindings. A Cloud Function can be invoked by allUsers (public without auth), allAuthenticatedUsers (any Google account) or by specific identities with roles/cloudfunctions.invoker or roles/run.invoker. The recurring flaw is deploying with allUsers for testing and forgetting to restrict it.
The third are the differences between gen1 and gen2. Gen2 runs on Cloud Run, inherits its security model, supports concurrency greater than 1, more efficient scaling to zero and better VPC integration. Gen1 is still available with its historical defaults. Distinguishing generation is part of the checklist because recommendations change.
The pentest is completed by reviewing VPC Service Controls around sensitive services (BigQuery, Cloud Storage), Eventarc for project event triggers, and coverage of Cloud Audit Logs (Admin Activity and Data Access) toward external destination.
Serverless hardening
Effective hardening rests on six blocks that should be applied as a set.
One IAM role per function. Breaking the convenient pattern of a shared role. Each function with its own role, scoped to concrete resource and action. AWS IAM Access Analyzer helps generate minimal policies based on actual usage in CloudTrail.
Secrets out of code and out of environment variables. Migration to Secrets Manager, Key Vault or Secret Manager with in-memory cache during execution to avoid latency penalties. Automated rotation where supported.
Dependency scanning. Snyk, Trivy, Grype or Dependabot/Renovate in pipeline. Deployment blocking if there is an unpatched critical CVE. For shared layers, strict version control and prior validation of every layer imported from outside the account.
Event source validation. JSON schemas with jsonschema or cerberus, type and length checks, expected fields before processing. Treating the event like untrusted HTTP input.
Rate limiting and concurrency limits. On AWS, reserved concurrency and throttling in API Gateway. On Azure, functionAppScaleLimit. On GCP, max-instances. Combined with budgets and alarms when cost deviates from baseline.
Observability. AWS X-Ray with active tracing, Application Insights with correct sampling, Cloud Trace and Cloud Profiler on GCP. Structured logs (JSON) to centralized destination with adequate retention. Without traces, detect and respond is blind.
CI/CD security
Serverless deployment is done from a pipeline. If the pipeline is misconfigured, it does not matter how secure the function code is. The operational rule today is OIDC instead of static keys.
In GitHub Actions you configure an OIDC provider on AWS (federated role with token.actions.githubusercontent.com:sub condition limiting to specific repo and branch), on Azure (federated credentials over App Registration) and on GCP (Workload Identity Federation). The pipeline obtains temporary credentials per execution, without long-lived keys in repo secrets.
In AWS CodePipeline and Azure DevOps, the equivalent is service roles with minimal scope. Any AWS_ACCESS_KEY_ID or AZURE_CLIENT_SECRET with infinite expiration in a pipeline is a critical finding.
The block is completed by pre-deployment validation: checkov, tfsec, cfn-nag over IaC template, secret scanning with gitleaks or trufflehog, artifact signing with Cosign and manual approvals on production deployments.
Frequently asked questions
Is serverless more secure or less secure than containers?
Neither in absolute terms. It reduces host surface (OS patches, kernel hardening) which the provider takes on. It increases configuration surface (IAM, events, dependencies) which the client takes on. Well governed it can be more secure; poorly governed, more exposed because the abstraction hides decisions that would be explicit in a container.
Is per-function role granularity mandatory?
In any serious pentest it appears as a high severity recommendation when not followed. Not legally mandatory, mandatory by least privilege. The difference is between an attacker reading one DynamoDB table or reading all fifty tables in the account.
Is cold start a real attack vector?
Yes, rarely primary. It shows up in advanced pentests as a side-channel or as a denial of wallet vector. Cold start itself is not a vulnerability. What gets reported is when initialization code loads secrets into memory that persist across warm executions and become exposed if the function is later compromised.
How do you prevent supply chain in layers?
Three combined controls. First, strict policy on accepted layers: only internal or from audited providers. Second, version pinning by SHA instead of "latest" or unversioned ARN. Third, automated scanning of every imported layer before promotion. Where feasible, keeping the layer in an owned account with controlled replication.
How long does a serverless pentest take?
A scoped application with 10 to 20 functions takes five to seven working days. An organization with hundreds of functions across multiple accounts, varied triggers and associated pipelines requires three to four weeks. The longest phase is usually IAM review when roles have grown by inertia over years.
Is denial of wallet via massive scaling a real risk?
One of the most underestimated. Functions triggered by queues or events without throttling can generate five-figure bills within hours if an attacker saturates the source. Controls: aggressive budget alarms, per-function concurrency limits, origin validation at the trigger and explicit throttling instead of infinite scaling where business allows.
Related resources
- Cloud penetration testing (AWS, Azure and GCP): technical guide
- Cloud misconfiguration errors in AWS and Azure
- Kubernetes pentesting: cluster attacks and production hardening
- Software supply chain attacks and DevSecOps
- What is Zero Trust: architecture and implementation
Serverless audit with Secra
At Secra we run dedicated offensive audits of serverless architectures on AWS Lambda, Azure Functions and GCP Cloud Functions. The scope covers exhaustive review of IAM roles and effective permissions per function, analysis of event sources and input validation, scanning of dependencies and layers, CI/CD pipeline review focused on OIDC and static secrets, and a prioritized hardening plan that integrates with NIS2, ENS and ISO 27001. Each finding ships with a reproducible attack chain and severity justified by business impact.
If your team operates serverless functions in production and you want to know the real security posture, let's talk and we will design the pentest scope together.
About the author
Secra Solutions team
Ethical hackers with OSCP, OSEP, OSWE, CRTO, CRTL and CARTE certifications, 7+ years of experience in offensive cybersecurity, and authors of CVE-2025-40652 and CVE-2023-3512.