Back to Checks
aws

Lambda function does not use cross-account layers

awslambda_function_using_cross_account_layers
Service: awslambdaSeverity: high
OfficialBuilt-inVerified
Categories:software-supply-chain
Resource Type:AwsLambdaFunction

AWS Lambda functions use only layers published within the same AWS account, rather than layers owned by external accounts.

A Lambda layer bundles shared code or dependencies that are injected into the function execution environment at runtime.

Risk

A layer from an external account is a supply chain dependency outside your control. If that account is compromised or the layer is updated maliciously, every consumer function executes attacker code with its IAM role — a direct privilege escalation and lateral movement path across all functions using that layer.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks awslambda_function_using_cross_account_layers

Recommendation

Eliminate cross-account layer dependencies by hosting all layers in your own AWS account.

  • Audit all layers with aws lambda get-function-configuration and inspect Layers[].Arn
  • Extract the account ID from the ARN (field 5 in colon-split) and compare against your account
  • For approved vendor layers, pin to a specific immutable version ARN and review on each update
  • Enforce this via SCP: deny lambda:UpdateFunctionConfiguration when lambda:Layer ARN does not match your account ID

Remediation

CLI

# Copy the cross-account layer version into your own account first:
aws lambda publish-layer-version --layer-name <layer-name> --zip-file fileb://<layer.zip>
# Then update the function to use your own layer ARN:
aws lambda update-function-configuration --function-name <function-name> --layers <your-account-layer-arn>

Terraform

resource "aws_lambda_layer_version" "example" {
  layer_name = "<layer-name>"
  filename   = "<layer.zip>"
}

resource "aws_lambda_function" "example" {
  function_name = "<example_resource_name>"
  role          = "<example_role_arn>"
  handler       = "index.handler"
  runtime       = "python3.12"
  filename      = "<example_package.zip>"

  layers = [aws_lambda_layer_version.example.arn]
}

NativeIaC

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  OwnedLayer:
    Type: AWS::Lambda::LayerVersion
    Properties:
      LayerName: <layer-name>
      Content:
        S3Bucket: <bucket>
        S3Key: <key>
  LambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: <example_resource_name>
      Role: <example_role_arn>
      Handler: index.handler
      Runtime: python3.12
      Code:
        S3Bucket: <example_code_bucket>
        S3Key: <example_code_key>
      Layers:
        - !Ref OwnedLayer

Other

1Download the cross-account layer ZIP
2Publish the layer in your own account: Lambda > Layers > Create layer
3Update the function configuration to reference your layer ARN
4Remove the cross-account layer ARN from the function

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.awslambda.awslambda_client import awslambda_client


class awslambda_function_using_cross_account_layers(Check):
    def execute(self):
        findings = []
        for function in awslambda_client.functions.values():
            report = Check_Report_AWS(metadata=self.metadata(), resource=function)
            cross_account_layers = [
                layer
                for layer in function.layers
                if layer.account_id != awslambda_client.audited_account
            ]
            if not function.layers:
                report.status = "PASS"
                report.status_extended = (
                    f"Lambda function {function.name} does not use any layers."
                )
            elif cross_account_layers:
                report.status = "FAIL"
                layer_arns = ", ".join(layer.arn for layer in cross_account_layers)
                report.status_extended = (
                    f"Lambda function {function.name} uses cross-account "
                    f"layer(s): {layer_arns}."
                )
            else:
                report.status = "PASS"
                report.status_extended = (
                    f"Lambda function {function.name} only uses layers "
                    f"from the same account ({awslambda_client.audited_account})."
                )
            findings.append(report)
        return findings