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.
| Capability | Required? | Risk |
|---|
| Read application logs | Yes | Low |
| Read deployment status | Yes | Low |
| Read S3 objects | Maybe | Medium |
| Write S3 objects | Maybe | Medium |
| Start build | Yes | Medium |
| Deploy application | Restricted | High |
| Modify IAM | No | Critical |
| Delete infrastructure | No | Critical |
| Change network rules | No | Critical |
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:
| Role | Typical Access |
|---|
| AI-Dev | Development resources |
| AI-Test | Test infrastructure |
| AI-Deploy | Controlled deployment |
| AI-Prod-ReadOnly | Production 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:
| Operation | Expected |
|---|
| Read development S3 object | Allow |
| Write development artifact | Allow |
| Read production logs | Maybe allow |
| Modify production Lambda | Deny |
| Delete development bucket | Deny unless required |
| Delete production bucket | Deny |
| Read development secret | Only if required |
| Read production secret | Deny |
| Modify IAM role | Deny |
| Assume test role | Allow if required |
| Assume production admin | Deny |
| Change production security group | Deny |
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:
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.