# IAM Policy Evaluation Edge Cases That AI Agents Frequently Misinterpret

> Discover IAM policy evaluation edge cases AI agents misinterpret, including missing session tags, transitive tag failures, and unmet condition keys. Improve your AWS security.

- Repository: [Amazon Web Services/agent-toolkit-for-aws](https://github.com/aws/agent-toolkit-for-aws)
- Tags: best-practices
- Published: 2026-07-03

---

**AI agents operating through the AWS Agent Toolkit often encounter IAM access denials due to missing session tags, transitive tag propagation failures in role chaining, and unmet service-specific condition keys like `aws:SourceArn` that developers forget to include in cross-account or pass-role scenarios.**

The AWS Agent Toolkit for AWS equips AI-assisted coding agents with **plugins**, **skills**, and an **AWS MCP Server** that enforce strict IAM controls by automatically injecting identity metadata into API requests. When policies rely on condition keys such as `aws:PrincipalTag/AgentID` or `aws:CalledVia` to restrict actions to agent-only contexts, subtle evaluation edge cases can trigger unexpected denials or permission leaks. Understanding these IAM policy evaluation edge cases is essential for writing secure, agent-aware policies that isolate agent permissions from broader developer IAM roles.

## How the AWS Agent Toolkit Enforces IAM Controls

The toolkit routes all agent-initiated AWS calls through the MCP Server, which automatically attaches the agent’s identity as an IAM principal and injects **IAM condition keys** describing who the agent is and how it is acting. According to the repository’s documentation in [`README.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/README.md) at lines 162-166, this design deliberately isolates agent permissions from the developer’s IAM role, enabling policies that allow actions only when they originate from an agent. The [`rules/aws-agent-rules.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/rules/aws-agent-rules.md) file at lines 9-11 provides agents with explicit guidance to verify IAM-related details before acting, ensuring that condition keys like `aws:PrincipalTag/AgentID` and `aws:CalledVia` are present in every request.

## Six Critical IAM Policy Evaluation Edge Cases

### Missing or Mismatched Condition Tags

The agent must include the exact tag value the policy expects, such as `AgentID=xyz`. If the tag is omitted or a different value is supplied, the condition evaluates to `false`, resulting in "AccessDenied" even though the principal possesses the required IAM role. This occurs frequently when developers manually configure agents without using the toolkit’s automatic tag injection.

### Assume-Role Chaining Without Transitive Tags

When an agent assumes a role that itself assumes another role, condition keys are not automatically propagated unless explicitly passed through `TagSession` or `TransitiveTag` options. Policies that allow `sts:AssumeRole` with a tag condition may succeed initially, but subsequent AWS service calls fail because the downstream role lacks the original agent tags. The toolkit’s helper libraries mitigate this by propagating original tags via `TransitiveTagKeys`.

### Cross-Account Resource Policy Mismatches

Resource-based policies can grant permissions only when `aws:PrincipalOrgID` or `aws:PrincipalArn` matches a specific account. Agents running in a different account may be denied despite having sufficient role permissions, resulting in "AccessDenied" on S3 buckets or DynamoDB tables that are otherwise open to the role. The bucket policy must explicitly reference the agent’s principal ARN and expected tags.

### IAM Pass-Role with Missing Service-Specific Conditions

Services like Lambda and ECS require additional condition keys such as `aws:SourceArn` when a role is passed. The agent may correctly pass the role but omit the required source ARN, causing the policy to reject the request with an "InvalidParameterException: Missing required parameter ‘SourceArn’" error. This edge case requires explicit condition statements in the IAM policy that the agent cannot satisfy without proper configuration.

### Explicit Deny Evaluation with Unsupplied Condition Keys

An explicit `Deny` that uses a condition key not supplied by the agent, such as `aws:RequestedRegion`, will still block the action even if an `Allow` statement would otherwise succeed. This creates unexpected denials in regions where the agent is fully authorized, because the explicit deny logic evaluates independently of the presence of the condition key in the request context.

### Policy Size and Evaluation Limits

Large, complex policies containing many statements or nested `NotAction`/`NotResource` elements can hit the **5,000-statement evaluation limit**, causing requests to be rejected with a generic "Policy size exceeds the limit" error. This occurs during seemingly simple operations when policies accumulate deny statements or condition blocks for numerous edge cases.

## Practical Code Examples for Handling Edge Cases

### Assuming a Role with Session Tags

Use the `TagSession` and `TransitiveTagKeys` parameters to ensure tags survive role chaining:

```python
import boto3

sts = boto3.client('sts')
agent_id = "agent-1234"

resp = sts.assume_role(
    RoleArn='arn:aws:iam::111122223333:role/AgentRole',
    RoleSessionName='agent-session',
    Tags=[{'Key': 'AgentID', 'Value': agent_id}],
    TransitiveTagKeys=['AgentID']
)

creds = resp['Credentials']
client = boto3.client('s3',
                    aws_access_key_id=creds['AccessKeyId'],
                    aws_secret_access_key=creds['SecretAccessKey'],
                    aws_session_token=creds['SessionToken'])

```

The corresponding policy grants `s3:PutObject` only when the tag matches:

```json
{
  "Effect": "Allow",
  "Action": "s3:PutObject",
  "Resource": "arn:aws:s3:::my-bucket/*",
  "Condition": {
    "StringEquals": {
      "aws:PrincipalTag/AgentID": "agent-1234"
    }
  }
}

```

### Enforcing Agent Identity with aws:CalledVia

The toolkit’s `asm-exec` wrapper automatically injects required condition keys:

```bash
asm-exec python create_table.py \
    --agent-id ${AGENT_ID} \
    --region us-east-1

```

This ensures the request carries `aws:PrincipalTag/AgentID` and `aws:CalledVia` = `aws-agent-toolkit`. The matching policy requires:

```json
{
  "Effect": "Allow",
  "Action": "dynamodb:CreateTable",
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "aws:CalledVia": "aws-agent-toolkit"
    }
  }
}

```

### Handling Cross-Account Resource Policies

When accessing a bucket in another account, the resource policy must reference the agent’s principal ARN:

```json
{
  "Sid": "AllowAgentRead",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::111122223333:role/AgentRole"
  },
  "Action": ["s3:GetObject"],
  "Resource": "arn:aws:s3:::shared-bucket/*",
  "Condition": {
    "StringEquals": {
      "aws:PrincipalTag/AgentID": "agent-1234"
    }
  }
}

```

## Key Source Files in the Agent Toolkit

- **[`plugins/aws-core/hooks/secret-safety.py`](https://github.com/aws/agent-toolkit-for-aws/blob/main/plugins/aws-core/hooks/secret-safety.py)** – Enforces secret-handling guardrails that prevent agents from leaking credentials in IAM contexts.
- **[`README.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/README.md)** (repo root) – Documents the overall architecture and the role of IAM condition keys in agent isolation at lines 162-166.
- **[`rules/aws-agent-rules.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/rules/aws-agent-rules.md)** – Provides explicit guidance for agents to verify IAM-related details before acting at lines 9-11.
- **[`skills/specialized-skills/database-skills/amazon-elasticache/scripts/test_connection.py`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/specialized-skills/database-skills/amazon-elasticache/scripts/test_connection.py)** – Implements concrete IAM authentication checks and prints helpful error messages when evaluations fail at lines 7-14.
- **[`skills/specialized-skills/analytics-skills/migrate-to-msk/scripts/compatibility.py`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/specialized-skills/analytics-skills/migrate-to-msk/scripts/compatibility.py)** – Defines constants for IAM-related connection limits (e.g., `EXPRESS_MAX_IAM_CONNS_PER_BROKER`) that illustrate how IAM authentication factors into service-specific quotas at lines 714-734.

## Summary

- **Condition key propagation** failures during role chaining cause silent denials when `TransitiveTagKeys` are omitted from `sts:AssumeRole` calls.
- **Cross-account resource policies** must explicitly reference the agent’s principal ARN and expected tags, not just the assumed role.
- **Service-specific conditions** like `aws:SourceArn` are mandatory for IAM pass-role operations in Lambda and ECS, and agents must include them in the request context.
- **Explicit deny statements** evaluate independently of whether the agent supplies the condition key, potentially blocking authorized actions.
- **Policy size limits** of 5,000 statements can trigger unexpected errors when complex agent policies accumulate edge-case handling rules.
- **Toolkit utilities** like `asm-exec` and the MCP Server automatically inject standard condition keys, reducing the risk of missing tag mismatches.

## Frequently Asked Questions

### Why does my agent get "AccessDenied" despite having the correct IAM role?

This typically occurs when the IAM policy includes condition keys like `aws:PrincipalTag/AgentID` that the agent’s request does not include. Verify that the agent injected the correct tags during the `sts:AssumeRole` call or use the toolkit’s `asm-exec` wrapper to automatically handle tag propagation.

### How do I fix permission failures when my agent assumes a role that assumes another role?

You must enable `TagSession` on every `sts:AssumeRole` call and specify `TransitiveTagKeys` to ensure condition keys propagate through the chain. Without this, the second assumed role loses the original agent identity tags, causing downstream service calls to fail.

### What causes "InvalidParameterException: Missing required parameter ‘SourceArn’" when passing IAM roles?

Services like Lambda and ECS require the `aws:SourceArn` condition key in the IAM policy when passing roles. The agent must include this in the request context, or you must adjust the policy to allow the pass-role action without that specific condition if the service supports it.

### Do explicit deny statements in IAM policies affect agents differently than allow statements?

Yes. An explicit `Deny` with a condition key evaluates to `true` if the condition key is missing from the request, whereas an `Allow` with a condition key evaluates to `false`. This means a missing `aws:RequestedRegion` condition in the agent’s request will trigger an explicit deny but would not trigger an explicit allow, creating asymmetric blocking behavior.