Managing IAM Role Trust Policies with aws:SourceAccount and aws:SourceArn Conditions

You can prevent confused deputy attacks by adding aws:SourceAccount and aws:SourceArn condition keys to IAM role trust policies, ensuring that only specific AWS resources in designated accounts can assume the role.

The aws/agent-toolkit-for-aws repository demonstrates security best practices by implementing these conditions across serverless and event-driven architectures. These global condition keys restrict the sts:AssumeRole action to verified sources, eliminating the risk of unauthorized cross-account access through service intermediaries.

Understanding the Confused Deputy Vulnerability

When an AWS service assumes a role on behalf of a requester, trust policies lacking proper condition keys create a vulnerability where any AWS account could potentially manipulate the service into accessing your resources. This confused deputy attack vector occurs because the service principal (such as lambda.amazonaws.com or events.amazonaws.com) alone does not verify which specific account or resource initiated the request.

The aws:SourceAccount condition key validates that the request originates from a specific AWS account ID, while aws:SourceArn validates the exact ARN of the source resource. When combined, they ensure that only the intended resource in the intended account can trigger the role assumption.

Implementation Patterns in the Agent Toolkit

According to the source code in skills/core-skills/aws-iam/references/aws-iam-role-management.md, the toolkit enforces these safeguards by requiring both condition keys in trust policies for services that support them. The repository ships JSON template files that embed these conditions, placing placeholders for account IDs and resource ARNs that deployment scripts replace at runtime.

Trust Policy Structure

The standard pattern implemented across the toolkit follows this structure:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function"
        }
      }
    }
  ]
}

Practical Code Examples

The repository provides concrete implementations for various AWS services. These examples demonstrate how to scope role trust to specific resources.

Lambda Function Trust Policy

The file skills/specialized-skills/serverless-skills/processing-s3-uploads-with-step-functions/scripts/lambda-trust-policy.json contains the trust policy for Lambda execution roles:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function"
        }
      }
    }
  ]
}

Replace 123456789012 with your AWS account ID and update the ARN to match your specific Lambda function.

Step Functions Service Role

For Step Functions state machines, the repository uses a similar pattern in stepfunctions-trust-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "states.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:states:us-east-1:123456789012:stateMachine:MyStateMachine"
        }
      }
    }
  ]
}

EventBridge Rule Role

EventBridge rules that invoke targets require the same protection. The toolkit implements this in eventbridge-trust-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:events:us-east-1:123456789012:rule/MyRule"
        }
      }
    }
  ]
}

S3 Replication Role

For S3 replication scenarios, the trust policy targets the S3 service principal:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "s3.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:s3:::my-source-bucket"
        }
      }
    }
  ]
}

Key Files in the Repository

The aws/agent-toolkit-for-aws repository organizes these trust policies across several skills and plugins:

Summary

  • Always include both condition keys when creating trust policies for AWS services that support them to prevent confused deputy vulnerabilities.
  • aws:SourceAccount restricts access to a specific AWS account ID using the StringEquals operator.
  • aws:SourceArn restricts access to specific resource ARNs using the ArnLike operator for pattern matching.
  • The agent-toolkit-for-aws repository provides ready-to-use JSON templates in skills/specialized-skills/serverless-skills/processing-s3-uploads-with-step-functions/scripts/ that implement these security controls.
  • Replace placeholder values with actual account IDs and resource ARNs before deployment.

Frequently Asked Questions

What is the difference between aws:SourceAccount and aws:SourceArn?

aws:SourceAccount validates the AWS account ID that originated the request, preventing cross-account confused deputy attacks. aws:SourceArn validates the specific resource ARN, ensuring that only that particular resource (such as a specific Lambda function or S3 bucket) can assume the role. Using both provides defense in depth.

Which AWS services support these condition keys?

Most modern AWS services that can assume roles on your behalf support these keys, including Lambda, Step Functions, EventBridge, S3 (for replication), CloudTrail, DMS, and RDS. The aws/agent-toolkit-for-aws repository specifically implements these for serverless and event-driven services in the processing-s3-uploads-with-step-functions and aws-messaging-and-streaming skills.

Can I use aws:SourceAccount without aws:SourceArn?

While aws:SourceAccount alone restricts the assuming party to a specific account, it does not prevent other resources within that same account from assuming the role. Combining both keys ensures that only the specific resource you intend—such as a single Lambda function rather than any function in the account—can access the role.

How do I deploy these trust policies using the AWS CLI?

You can create the role using the JSON templates provided in the repository:

aws iam create-role \
  --role-name MySecureRole \
  --assume-role-policy-document file://skills/specialized-skills/serverless-skills/processing-s3-uploads-with-step-functions/scripts/lambda-trust-policy.json

Ensure you replace the placeholder account ID and ARN values in the JSON file before execution, or use infrastructure-as-code tools that substitute these values during deployment.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →