Back

SAS-4: Over-Privileged Function Permissions & Roles - Overview

What Are Over-Privileged Function Permissions?

Over-Privileged Function Permissions & Roles occurs when a serverless function is granted far more identity and access management (IAM) permission than it actually needs to do its job. Instead of being scoped to the one table it reads or the one bucket it writes, the function carries wildcard actions, wildcard resources, broad managed policies, or a single shared role reused across the whole application. The permission the function holds is much larger than the permission the function uses.

A serverless application is not one process—it is dozens or hundreds of small, independently deployed functions, each with its own execution role. That structure is a security opportunity: every function could be locked to exactly the handful of API calls it makes. Over-privilege throws that opportunity away. When a function's role says "Action": "*" on "Resource": "*", the function's actual code may only call dynamodb:GetItem on one table—but the credentials it is handed can do anything, anywhere, in the account.

Core Concept

Least-Privilege (secure):
  One role PER function
  Actions   -> only the exact API calls the code makes (dynamodb:GetItem)
  Resources -> specific ARNs (arn:aws:dynamodb:...:table/Orders)
  Conditions-> scoped further (aws:SourceArn, encryption context, index)
  Dangerous -> no iam:*, no unscoped iam:PassRole, no *:Delete* it never calls
  Blast radius on compromise -> one table, read-only

Over-Privileged (vulnerable):
  One SHARED role for every function in the app
  Actions   -> wildcards: "*", "s3:*", "dynamodb:*", "lambda:*"
  Resources -> "Resource": "*"  (every bucket, table, function, queue)
  Managed   -> broad AWS managed policies (e.g. *FullAccess) attached
  Dangerous -> iam:PassRole / iam:* present "just in case"
  Blast radius on compromise -> the entire cloud account

Why It's Critical for Serverless

Serverless concentrates several conditions that make over-privilege uniquely dangerous:

Why Does This Matter?

Business Impact

Technical Impact

Technical Context

Common Over-Privilege Scenarios in Serverless

1. A Single Shared Execution Role for Every Function

# serverless.yml - one broad role at the provider level, inherited by ALL functions
provider:
  name: aws
  iam:
    role:
      statements:
        - Effect: Allow
          Action: "*"          # every function gets every permission
          Resource: "*"        # ...on every resource
functions:
  createOrder:  { handler: create.handler }   # only needs PutItem on Orders
  healthCheck:  { handler: health.handler }   # needs nothing at all
  thumbnailer:  { handler: image.handler }    # only needs S3 on one bucket

Risk: The healthCheck function that needs no permissions carries the same account-wide power as everything else. Compromise the weakest function, own the account.

2. Wildcard Actions and Resources

{
  "Effect": "Allow",
  "Action": ["s3:*", "dynamodb:*"],
  "Resource": "*"
}

Risk: s3:* includes DeleteBucket, PutBucketPolicy, and read of every bucket; dynamodb:* includes DeleteTable and full scans of every table. The function almost certainly calls two or three of these actions on one resource.

3. Broad AWS Managed Policies

Attached to the execution role:
  AmazonS3FullAccess
  AmazonDynamoDBFullAccess
  AWSLambda_FullAccess

Risk: *FullAccess managed policies are convenient and enormous. They grant hundreds of actions across all resources of a service — the opposite of least privilege.

4. Unused Permissions Accumulating Over Time

Role granted in 2023: s3:GetObject on report-bucket   # feature since removed
Role granted in 2024: sqs:SendMessage on jobs-queue   # still used
Role granted in 2025: secretsmanager:GetSecretValue   # only used by 1 of 6 functions

Risk: Permissions are added when features ship but rarely removed when features are deleted. Roles ratchet only upward, so the granted set drifts far past the used set.

5. Privilege-Escalation Permissions (iam:PassRole / iam:*)

{
  "Effect": "Allow",
  "Action": ["iam:PassRole", "iam:AttachRolePolicy", "iam:CreatePolicyVersion"],
  "Resource": "*"
}

Risk: These are not data permissions—they are permissions to rewrite permissions. Unscoped iam:PassRole lets a function hand a powerful role to a service it controls; iam:AttachRolePolicy / CreatePolicyVersion let it grant itself admin.

6. Cross-Service Over-Permission

One function's role bundles:
  dynamodb:*   (data)
  s3:*         (storage)
  sns:*  sqs:* (messaging)
  ec2:*        (compute it never touches)
  kms:Decrypt on *  (every key in the account)

Risk: Even if each service grant were "only" what the function uses today, bundling many services into one role means any compromise reaches all of them at once.

Where Over-Privilege Enters

SourceTypical Over-PrivilegeConsequence
Provider-level roleOne shared role with wildcards inherited by all functionsUniform, account-wide blast radius
Hand-written policyAction: "*" / Resource: "*" "to make it work"Function can do anything, anywhere
Managed policies*FullAccess attached for convenienceHundreds of unused actions granted
Copy-paste IaCPermissive template reused across the fleetSame over-broad role everywhere
Permission driftGrants added per feature, never removedUsed set far smaller than granted set
IAM meta-permissionsUnscoped iam:PassRole / iam:*Privilege escalation to admin

Real-World Impact

The incidents below are described as classes of well-documented failure rather than specific named breaches; the pattern is what matters and it recurs across cloud environments.

Case Class 1: One Compromised Function, Whole-Account Reach

Over-Privilege:

Impact:

Root Cause: A wildcard role turned a single-function bug into a full-account data breach. A least-privilege role scoped to the one table would have contained it.

Case Class 2: Privilege Escalation via iam:PassRole

Over-Privilege:

Impact:

Root Cause: A permission to delegate roles was left unscoped. PassRole should always be constrained to specific, minimally-privileged role ARNs with a service condition.

Case Class 3: Managed *FullAccess Policy as the Default

Over-Privilege:

Impact:

Root Cause: Convenience defaults that were never replaced with a generated, least-privilege policy. Cloud providers now publish least-privilege guidance and analyzers precisely because this pattern is so common.

Prevalence and Statistics

Over-privileged function permissions are consistently identified as one of the most common and highest-impact issues in serverless security assessments, and least-privilege violations are among the most frequent findings in cloud security posture reviews generally.

Rather than cite precise percentages (which vary by source and year), the defensible picture is:

Note: exact figures differ between reports. The durable takeaway is that over-privilege is nearly ubiquitous, easy to introduce, and the single biggest factor in how far an attacker can travel after the first foothold.

Common Misunderstandings

Myth 1: "One shared role is simpler, and simpler is safer"

Reality: A shared role is simpler to write and far more dangerous to hold. It gives your least-trusted function the same power as your most-trusted one, so the weakest link defines the blast radius for the whole app.

Myth 2: "The function code only calls two APIs, so the wildcard is harmless"

Reality: Attackers do not run your code—they run their code with your role's credentials. What matters is what the role can do, not what your handler happens to call.

Myth 3: "It's an internal/background function, so permissions don't matter"

Reality: Internal functions are reached through injected events, poisoned queue messages, compromised dependencies, and lateral movement. An over-privileged background worker is a prime pivot target precisely because it is less scrutinised.

Myth 4: "We'll tighten the permissions later"

Reality: Permissions almost never get tightened after go-live; they only accumulate. The least-privilege policy must be generated and applied before production, then enforced so it cannot regress.

Myth 5: "iam:PassRole is just plumbing, not a real permission"

Reality: PassRole is one of the most abused escalation primitives in the cloud. Unscoped, it lets a low-privileged function borrow a high-privileged role. It must always be constrained to specific role ARNs and a service condition.

Myth 6: "*FullAccess managed policies are AWS-blessed, so they're fine"

Reality: Managed *FullAccess policies exist for convenience and breadth, not for least privilege. They grant hundreds of actions on all resources—the direct opposite of what a single function needs.

How Over-Privilege Differs from Related Issues

AspectOver-Privileged Roles (SAS-4)Event-Data Injection (SAS-1)Security Misconfiguration
Root causeRole grants exceed what the function usesUntrusted event data reaches a sinkInsecure settings/defaults
What it enablesBlast radius after a compromiseThe initial code executionRecon and easier footholds
Where it livesIAM policy / execution roleFunction handler logicConfig of every layer
Typical fixScope the role; one role per functionValidate/parameterise inputHarden and disable

SAS-1 and SAS-4 are the classic pairing: injection is how an attacker gets in, over-privilege is how far they get once inside. Fixing one without the other leaves the account exposed.

Key Takeaways

  1. The role is the perimeter—in serverless there is no host or network to fall back on, so an over-broad role is the breach surface.
  2. What the role can do, not what the code calls—attackers use the credentials, not your handler.
  3. One least-privilege role per function—shared and wildcard roles make the weakest function define the blast radius.
  4. Meta-permissions are the crown jewels—iam:* and unscoped iam:PassRole convert a foothold into account takeover.
  5. Granted drifts above used—permissions accumulate, so generate and re-verify least privilege continuously.

How to Identify if You're Vulnerable

Ask these questions about your serverless application:

If you answered "no" or "not sure" to several of these, one compromised function likely reaches far more of your account than it should.

Next Steps