iCapSolutions

Cloud Computing – DevSecOps – IT Services

Serverless Security Best Practices for 2026

Serverless computing removes servers from your to-do list, but not security. These serverless security best practices cover what changes when you move to functions, what stays your responsibility, and the specific controls that protect a serverless application in production. Examples use AWS Lambda, and the same ideas apply to Azure Functions and Google Cloud Run functions.

What Is Serverless Security?

Serverless security is protecting the parts of a serverless application the cloud provider doesn’t: your code, its permissions, its data, and the events that trigger it. Under the shared responsibility model, the split looks like this:

The provider securesYou secure
Physical hosts, hypervisor and operating systemFunction code and its dependencies
Runtime patching (for managed runtimes)IAM permissions for each function
Isolation between customers’ functionsInput validation for every event source
Availability and scaling of the platformSecrets, data encryption choices, and API authentication

How Serverless Improves Security, and What It Adds

Serverless genuinely removes some risks: there’s no operating system for you to patch, no long-running server for an attacker to settle into, and each function can have its own narrowly scoped permissions. But it adds others. An application becomes dozens of small functions, each with its own permissions and triggers, and every trigger (an HTTP request, a file upload, a queue message) is an input an attacker may control. The OWASP Serverless Top 10 lists event-data injection, broken authentication and over-privileged functions among the most common problems.

1. Give Every Function Its Own Least-Privilege Role

The most important practice is also the most often skipped. One shared role with broad permissions means one vulnerable function exposes everything. Scope each role to specific actions and resources:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["dynamodb:GetItem", "dynamodb:PutItem"],
    "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/orders"
  }]
}

Avoid "Action": "*" and "Resource": "*" in function roles. IAM Access Analyzer can generate a policy from a function’s actual CloudTrail activity, which is a fast way to tighten an existing role.

2. Validate Input from Every Event Source

Functions are triggered by far more than HTTP. An S3 object key, an SQS message body or a DynamoDB stream record can all carry attacker-controlled data. Validate every event against a schema before using it, never pass event fields directly into shell commands, SQL or file paths, and treat internal queues as untrusted if anything upstream accepts public input.

3. Keep Secrets Out of Code and Plain Environment Variables

  • Store credentials in AWS Secrets Manager or Systems Manager Parameter Store (SecureString), encrypted with KMS, and fetch them at runtime. Cache them for the life of the execution environment to keep latency and cost down.
  • If you must use environment variables, encrypt them with a customer-managed KMS key and limit who can read the function configuration.
  • Never commit secrets to the repository or bake them into deployment packages or layers.

4. Authenticate and Throttle Every Entry Point

  • Put API Gateway in front of public functions with a JWT or Cognito authorizer, or IAM authorization for service-to-service calls.
  • If you use Lambda function URLs, prefer AuthType: AWS_IAM. NONE makes the function publicly callable by anyone with the URL.
  • Set throttling limits on API stages and attach AWS WAF rules for common attacks and rate-based blocking.

5. Limit Timeouts and Concurrency to Prevent “Denial of Wallet”

Serverless scales automatically, and so does the bill when someone floods an endpoint. Set function timeouts close to real execution time rather than the maximum, use reserved concurrency to cap how far a single function can scale, and set billing alarms. This protects both your budget and the downstream databases that can’t scale as fast as Lambda.

6. Secure Dependencies and Deployments

  • Scan dependencies in CI (npm audit, pip-audit, or a scanner like Trivy) and fail builds on high-severity issues.
  • Keep functions on supported runtimes. Deprecated runtimes stop receiving security patches.
  • Use code signing for Lambda (with AWS Signer) so only packages your pipeline signed can be deployed.
  • Deploy through infrastructure as code (Terraform, AWS SAM or CDK) so permissions are reviewed in pull requests, not clicked together in the console.

7. Log, Trace and Detect

  • Enable CloudTrail for management events, and data events for sensitive functions and buckets.
  • Send structured logs to CloudWatch Logs with a sensible retention period, and never log secrets or full request payloads with personal data.
  • Use X-Ray or OpenTelemetry tracing to see how requests flow across functions.
  • Turn on GuardDuty Lambda Protection to flag functions communicating with known malicious hosts.

8. Use Network Controls Only Where They Help

Functions don’t need to be in a VPC unless they reach private resources such as an RDS database. When they do, use private subnets, security groups scoped to exactly the ports needed, and VPC endpoints for AWS services, so traffic to S3 or DynamoDB doesn’t leave the AWS network.

The Same Controls on Azure and Google Cloud

The practices above aren’t AWS-specific. Here’s where each one lives on the other two major platforms:

ControlAWS LambdaAzure FunctionsGoogle Cloud Run functions
Per-function identityIAM execution roleManaged identityDedicated service account
SecretsSecrets Manager, Parameter StoreKey Vault referencesSecret Manager
Public entry point authAPI Gateway authorizers, IAM function URLsApp Service authentication, API ManagementIAM invoker role, API Gateway
Scaling capsReserved concurrencyMaximum scale-out settingMaximum instances
Threat detectionGuardDuty Lambda ProtectionMicrosoft Defender for CloudSecurity Command Center

The most common mistake on every platform is the same: reusing one broad identity across many functions. On Google Cloud in particular, functions fall back to a default service account unless you assign one, and that account often has far more access than any single function needs.

Serverless Security Checklist

CheckDone when
Per-function IAM rolesNo wildcard actions or resources in function policies
Input validationEvery trigger’s event is schema-validated
SecretsAll credentials come from Secrets Manager or Parameter Store
Entry pointsEvery public API or function URL requires authentication and is throttled
Cost guardrailsTimeouts, reserved concurrency and billing alarms are set
Supply chainDependency scanning in CI, supported runtimes, code signing
VisibilityCloudTrail, structured logs, tracing and GuardDuty enabled

The AWS Lambda security documentation goes deeper on each control. If your stack also runs containers, our Kubernetes security best practices guide covers the equivalent controls for clusters. And if you’d like help reviewing a serverless application’s permissions and entry points, our cloud and DevSecOps services start with exactly that review.

Related Reading