AWS  

Building Least-Privilege IAM Policies for AI Coding Agents

AI coding agents are becoming capable of doing much more than generating code.

A modern coding agent can inspect repositories, execute commands, create files, run tests, interact with cloud services, modify infrastructure, and sometimes deploy changes. That capability makes agents useful, but it also creates a security problem that traditional developer tooling did not have to solve in quite the same way.

A developer may understand the consequences of an AWS command before running it. An AI agent may generate and execute the command because it believes the requested task requires it.

The security boundary therefore needs to exist outside the model.

For AWS-based development environments, one of the most important controls is least-privilege IAM. The goal is to give an AI coding agent enough permission to complete its assigned work while preventing it from making unrelated or dangerous infrastructure changes.

This article explains how to design IAM policies for AI coding agents, how to separate development permissions from deployment permissions, how to restrict resources and actions, and how to test whether an agent can accidentally cross its intended security boundary.

Why AI Coding Agents Need a Different Permission Model

Traditional developer access often grows organically.

A developer starts with:

Read source code
Run tests
Build application

Over time, additional permissions are added:

Read database
Deploy application
Modify infrastructure
Read logs
Manage queues
Access storage

Eventually, the developer may have broad permissions simply because removing them is inconvenient.

Applying the same model to an AI coding agent is risky.

An agent may be given tools that allow it to execute:

AWS CLI
Shell commands
Infrastructure tools
Git operations
Package managers
Cloud APIs

If the underlying IAM principal has broad privileges, the agent effectively inherits them.

The important security principle is:

Agent capability
    +
Tool capability
    +
IAM permissions
    =
Effective agent authority

IAM therefore becomes one of the critical enforcement layers.

Start With the Agent's Actual Responsibilities

Do not begin by writing an IAM policy.

Begin by defining what the agent is supposed to do.

For example, an AI coding agent responsible for reviewing a .NET application may need:

Read repository files
Run dotnet build
Run dotnet test
Read application logs
Read deployment metadata

It probably does not need:

Delete databases
Modify IAM
Create users
Change billing configuration
Disable logging
Modify production networking

Create a capability matrix before assigning permissions.

CapabilityRequired?Risk
Read application logsYesLow
Read deployment statusYesLow
Read S3 objectsMaybeMedium
Write S3 objectsMaybeMedium
Start buildYesMedium
Deploy applicationRestrictedHigh
Modify IAMNoCritical
Delete infrastructureNoCritical
Change network rulesNoCritical

This becomes the foundation for the IAM policy.

Separate Coding From Deployment

One of the strongest architectural controls is separating development permissions from deployment permissions.

A coding agent may need to:

Build
Test
Analyze
Read logs
Inspect configuration

That does not mean it should be allowed to deploy.

Use separate roles or permission boundaries:

AI Coding Role
    |
    +--> Repository access
    +--> Build/test resources
    +--> Limited read-only cloud access

Deployment Role
    |
    +--> Deployment permissions
    +--> Infrastructure permissions

The deployment role should not automatically become available simply because the coding agent can execute shell commands.

This creates a meaningful security boundary.

Use Resource-Level Restrictions

Avoid policies that grant broad actions across an entire AWS account.

For example, this is extremely broad:

{
  "Effect": "Allow",
  "Action": "s3:*",
  "Resource": "*"
}

It allows the principal to perform every S3 action against every resource covered by the policy.

A more restrictive policy identifies the required resource.

For example:

{
  "Effect": "Allow",
  "Action": [
    "s3:GetObject"
  ],
  "Resource": "arn:aws:s3:::my-build-artifacts/*"
}

The exact ARN should match the application's resource structure.

The principle is more important than the example:

Required action
+
Required resource
+
Required scope

Avoid wildcard permissions when the resource can be identified precisely.

Restrict Actions as Well as Resources

Resource restrictions alone are not sufficient.

Suppose an agent needs to read objects from a bucket.

It may need:

s3:GetObject

It probably does not need:

s3:DeleteObject
s3:PutObject
s3:PutBucketPolicy
s3:DeleteBucket

Keep the action set as small as possible.

A policy should answer:

What exact API operation does the agent need?

If the answer is "only read an object," granting the entire service is unnecessary.

Be Careful With IAM Permissions

IAM permissions are particularly sensitive.

An AI coding agent should generally not have broad permissions such as:

iam:*

or:

iam:CreateRole
iam:AttachRolePolicy
iam:PutRolePolicy
iam:PassRole

unless the workflow explicitly requires them and they are tightly constrained.

IAM changes can alter the security boundary of the entire account.

A particularly important permission is:

iam:PassRole

If an agent can create or modify resources and pass a highly privileged role to those resources, the effective authority can become much larger than the agent's direct permissions suggest.

For this reason, iam:PassRole should be treated as a high-risk permission and restricted to specific roles where it is genuinely required.

Understand Indirect Privilege Escalation

Least privilege is not simply:

"Does the policy contain AdministratorAccess?"

An agent can potentially combine individually permitted operations into a more powerful action.

For example:

Create resource
+
Pass privileged role
+
Execute code
=
Potential privilege escalation

Another example could involve:

Modify policy
+
Access resource
=
Expanded authority

This is why IAM design must consider permission combinations, not just individual actions.

Use Permission Boundaries Where Appropriate

A permission boundary can provide an additional limit on what permissions a principal can effectively receive.

Conceptually:

Identity Policy
      |
      v
Permission Boundary
      |
      v
Effective Permissions

Even if an identity policy becomes broader, the boundary can restrict the maximum permissions available.

This is especially useful in environments where an AI agent or automated workflow can create subordinate resources or roles.

The boundary should itself be protected from modification by the agent.

An agent should not be able to change the mechanism that limits its authority.

Consider Separate AWS Accounts

For high-risk AI development workloads, account separation can provide a stronger boundary than IAM alone.

For example:

Development Account
    |
    +--> AI coding agent
    +--> Test infrastructure
    +--> Temporary resources

Production Account
    |
    +--> Production services
    +--> Production databases
    +--> Deployment controls

The coding agent may have meaningful permissions in the development account while having no direct access to production.

This reduces the blast radius of an agent mistake.

Even if the agent executes a destructive command, the damage is limited to the environment where it has authority.

Use Environment-Specific Roles

Another practical model is:

AI-Dev-Role
AI-Test-Role
AI-Deploy-Role
AI-Production-ReadOnly-Role

Each role should have a clearly defined purpose.

For example:

RoleTypical Access
AI-DevDevelopment resources
AI-TestTest infrastructure
AI-DeployControlled deployment
AI-Prod-ReadOnlyProduction diagnostics

The agent should use the smallest role required for the current task.

Protect Production From Coding Tools

A coding agent may need to inspect production logs to diagnose a problem.

That does not mean it should be able to modify production.

A useful pattern is:

Production
   |
   +--> Read-only diagnostics
   |
   X--> Infrastructure modification
   X--> Database deletion
   X--> IAM modification

For example, an agent might receive read-only access to a log group while having no permissions to modify the associated compute, network, or database resources.

This allows debugging without turning the agent into a production administrator.

Restrict Secrets Access

Secrets are another important boundary.

Avoid giving an AI coding agent broad access to secrets simply because an application uses them.

For example, this is dangerous:

{
  "Effect": "Allow",
  "Action": "secretsmanager:GetSecretValue",
  "Resource": "*"
}

If the agent only needs one development secret, restrict the resource to that secret.

Even then, consider whether the agent actually needs the secret value.

Often the better architecture is:

Agent
   |
   v
Application configuration
   |
   v
Runtime retrieves secret

rather than exposing credentials directly to the agent.

The less sensitive information the agent can read, the smaller the impact of accidental disclosure.

Restrict KMS Permissions

Encryption keys require similar care.

Avoid broad permissions such as:

kms:*

when the application needs only a small subset of operations.

For example, a service may need:

kms:Decrypt

for one specific key.

Keep the resource and action scope narrow.

KMS permissions should be reviewed together with the services that use the key because indirect access can matter.

Add Conditions to Policies

IAM conditions can make policies significantly more precise.

For example, conditions can restrict permissions based on attributes such as:

Resource tags
Source identity
Requested region
Principal context
Encryption requirements

A conceptual policy might look like:

{
  "Effect": "Allow",
  "Action": "ec2:DescribeInstances",
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "aws:RequestedRegion": "us-east-1"
    }
  }
}

Not every AWS action supports resource-level restrictions or every condition key, so the policy should be validated against the specific IAM action being used.

The important point is that conditions can narrow access when an ARN alone is insufficient.

Use Tags to Create Boundaries

For development infrastructure, resource tags can help enforce ownership boundaries.

For example:

Environment = AI-Dev
Owner = CodingAgent
Project = Checkout

Then policies can be designed around those attributes where the relevant AWS service and IAM condition support them.

This allows a development agent to operate on its own temporary resources without automatically receiving access to unrelated infrastructure.

Control sts:AssumeRole

Role assumption is another critical boundary.

A coding agent may need to assume a role for a particular task.

Avoid:

{
  "Effect": "Allow",
  "Action": "sts:AssumeRole",
  "Resource": "*"
}

when only one or two roles are required.

Instead, identify the exact roles the agent can assume.

Conceptually:

AI Coding Role
      |
      +--> AssumeRole --> AI-Test-Role
      |
      X--> AssumeRole --> Production-Admin

The trust policy of the target role should also be reviewed.

Least privilege requires both sides of the role assumption relationship to be correct.

Build a Deny Strategy for High-Risk Actions

Allow policies define what the agent can do.

Explicit deny policies can provide additional protection for especially dangerous operations.

Examples may include:

Delete production database
Modify IAM
Disable audit logging
Delete security controls
Change production network boundaries

However, explicit denies should be designed carefully. They can create confusing authorization behavior if applied without a clear policy model.

A better approach is to first create a strong allow-list and then use denies for important guardrails that must hold across multiple permission sources.

Keep Audit Logging Enabled

You need visibility into what the agent actually does.

Monitor API activity through appropriate AWS audit mechanisms and collect:

Principal
Action
Resource
Timestamp
Source
Success/failure

This helps answer questions such as:

Which permission did the agent actually use?
Which API did it call?
Which resource did it modify?
Was the action expected?

A policy that looks least-privileged on paper may still grant more access than the workload needs.

Actual usage data helps tighten it.

Build a Permission Usage Baseline

Start with a broader but controlled policy in a non-production environment.

Run representative agent tasks.

Collect the API actions actually used.

For example:

s3:GetObject
logs:GetLogEvents
lambda:GetFunction
cloudformation:DescribeStacks

Then remove permissions that were never used.

Repeat the process.

This creates a feedback loop:

Initial policy
      |
      v
Agent workload
      |
      v
Observed permissions
      |
      v
Remove unused access
      |
      v
Test again

This is much safer than guessing every required permission from the beginning.

Test Dangerous Commands Explicitly

Least privilege should be tested adversarially.

Ask whether the agent can execute commands such as:

Delete an S3 bucket
Delete a database
Modify an IAM role
Attach an administrator policy
Pass a production role
Disable logging
Modify security groups
Delete a production function

The expected result should be denial.

Do not assume a policy is safe because it looks restrictive.

Verify it.

Example Policy Testing Matrix

A practical test matrix could look like:

OperationExpected
Read development S3 objectAllow
Write development artifactAllow
Read production logsMaybe allow
Modify production LambdaDeny
Delete development bucketDeny unless required
Delete production bucketDeny
Read development secretOnly if required
Read production secretDeny
Modify IAM roleDeny
Assume test roleAllow if required
Assume production adminDeny
Change production security groupDeny

The exact expected behavior depends on the agent's job.

The important part is that every permission has an intentional answer.

Use Infrastructure as Code for IAM

Do not manually create important AI-agent IAM policies in the console and leave them undocumented.

Store policies in version-controlled infrastructure code.

For example:

infrastructure/
    iam/
        ai-coding-role.tf
        ai-test-role.tf
        permissions-boundary.tf

This gives you:

  • Code review.

  • Version history.

  • Reproducible environments.

  • Automated testing.

  • Easier rollback.

  • Clear ownership.

An AI agent's permissions should themselves be treated as production-grade infrastructure.

Review IAM Changes Like Application Code

An AI-generated pull request that changes application code may be risky.

An AI-generated pull request that changes IAM deserves even more scrutiny.

A review should ask:

Why is this permission required?
What resource does it access?
Can the resource be narrowed?
Can the action be narrowed?
Can the permission be removed?
Can the task be performed with a read-only role?
Does the permission enable role assumption?
Does it enable privilege escalation?
Does it affect production?

Avoid approving IAM changes simply because the application failed without them.

The agent should not automatically receive additional permissions just to make a task succeed.

Common Mistakes

Giving the Agent AdministratorAccess

This defeats the purpose of least privilege and dramatically increases blast radius.

Using Resource: "*" Everywhere

Some AWS actions require "*", but using it by default is poor policy design.

Allowing iam:*

IAM administration should be separated from normal coding activity.

Ignoring iam:PassRole

This permission can create significant indirect authority when combined with resource creation or modification.

Allowing Broad Role Assumption

An unrestricted sts:AssumeRole permission can undermine otherwise restrictive policies.

Giving Production Write Access for Debugging

Production diagnostics generally require much less access than production modification.

Exposing Secrets to the Agent

If the agent does not need the actual secret value, do not give it permission to retrieve it.

Never Testing Denials

A secure policy should prove that dangerous operations fail, not merely that required operations succeed.

Troubleshooting AccessDenied

Least-privilege policies can initially produce legitimate AccessDenied errors.

Do not respond by adding:

Action: "*"

or:

Resource: "*"

Instead, identify the exact denied operation.

For example:

AccessDenied
    |
    v
Which API action?
    |
    v
Which resource?
    |
    v
Why is it required?
    |
    v
Can scope be narrowed?

Then add the smallest permission necessary.

Also remember that effective AWS permissions can be influenced by multiple mechanisms, including identity policies, resource policies, permission boundaries, session policies, and organization-level controls.

The correct fix is therefore not always another identity-policy statement.

A Practical IAM Design Pattern

A useful architecture for an AI coding agent looks like this:

                    AI Coding Agent
                           |
                           v
                    AI-Coding-Role
                           |
            +--------------+--------------+
            |              |              |
            v              v              v
      Dev Resources    Read-Only       Build/Test
                       Diagnostics      Resources
            |
            X
            |
     Production Write
            |
          DENIED

A separate controlled deployment process handles production changes:

AI Coding Agent
       |
       v
Pull Request
       |
       v
Automated Tests
       |
       v
Human / Policy Approval
       |
       v
Deployment Role
       |
       v
Production

This creates a stronger boundary than giving the coding agent direct production deployment authority.

Frequently Asked Questions

Should an AI coding agent have AWS credentials?

Only when the task genuinely requires AWS API access. Prefer temporary, scoped credentials and role-based access over long-lived credentials.

Should the agent have AdministratorAccess?

No, not as a normal coding-agent permission model. Administrative access dramatically increases the consequences of an agent mistake or compromised tool.

Can an AI coding agent deploy applications?

It can, but deployment should generally be separated from normal coding permissions. A controlled deployment role and approval mechanism provide a stronger security boundary.

What is the most dangerous IAM permission for an AI agent?

There is no single universally most dangerous permission. Broad IAM modification, unrestricted role assumption, iam:PassRole, and permissions that can modify security boundaries are particularly important to review.

Should production access be completely blocked?

For many coding agents, production write access should be blocked. Read-only diagnostic access may be appropriate when debugging production issues.

How do I know which permissions the agent actually needs?

Run representative workloads in a controlled environment, collect audit data showing the APIs used, and iteratively remove permissions that are not required.

Is IAM enough to secure an AI coding agent?

No. IAM controls AWS authorization, but the overall security boundary should also include tool restrictions, repository permissions, secret management, network controls, code review, logging, and deployment controls.

Conclusion

AI coding agents change the security model because they combine software development capabilities with automated tool execution. If an agent can execute cloud commands, its effective authority is ultimately constrained by the credentials and permissions available to those commands.

Least-privilege IAM should therefore be designed around the agent's actual responsibilities, not around the permissions a developer happens to have. Start with a narrow capability matrix, restrict actions and resources, separate coding from deployment, protect IAM and secrets, tightly control role assumption, and use permission boundaries or account separation when stronger isolation is required.

Most importantly, test the policy from both directions. Verify that legitimate development tasks work and that dangerous operations fail. An AI agent should be able to complete its assigned task without being able to turn a coding mistake into an infrastructure-wide security incident.

The strongest design is usually not to make the AI agent powerful and trust it to behave correctly. It is to make the security boundary strong enough that even an incorrect command, hallucinated infrastructure change, or compromised tool cannot exceed the authority required for the job.