You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
s3 cp with dryrun flag does not properly check IAM permissions #9935
will succeed (exit code 0), even if the same command without the dryrun flag fails with an unauthorized error. this is not true of the reverse (download vs upload) and sync dryrun works properly.
Regression Issue
Select this option if this issue appears to be a regression.
Expected Behavior
The --dryrun flag should properly validate IAM permissions to upload an object and exit with the proper code
$ aws s3 cp {my-local-file} 's3://restricted-bucket/{remote-file}'
upload failed: ./{my-local-file} to s3://restricted-bucket/{remote-file} An error occurred (AccessDenied) when calling the PutObject operation: User: arn:aws:sts::{account}:assumed-role/{role-name}/{user-name} is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::restricted-bucket/{remote-file}" because no identity-based policy allows the s3:PutObject action
$ echo $?
1
Download
$ aws s3 cp 's3://restricted-bucket/{remote-file}' {my-local-file} --dryrun
fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
$ echo $?
1
Reproduction Steps
create a bucket that has restrictive permissions to the test user
run the aws s3 cp commands as described (dryrun vs no dryrun)
observe the behavior
Possible Solution
the dryrun flag should validate whether or not the user has permissions to be able to perform the command. It should behave similarly to all other aws cli commands and return a proper error message and exit code
Hi @ps06756, thanks for your patience. After reviewing with the team, we've agreed not to make changes to the implementation. --dryrun isn't really intended to validate IAM permissions. Instead, it's meant to communicate what operations would be ran assuming permissions exist. The download implementation needs a HeadObject operation because without it, the CLI would always claim that a s3://mybucket/object -> ./object operation will happen, even if object doesn’t exist in the S3 bucket. Please let me know if you have any follow-up questons.
Hi @ps06756, thanks for your patience. After reviewing with the team, we've agreed not to make changes to the implementation. --dryrun isn't really intended to validate IAM permissions. Instead, it's meant to communicate what operations would be ran assuming permissions exist. The download implementation needs a HeadObject operation because without it, the CLI would always claim that a s3://mybucket/object -> ./object operation will happen, even if object doesn’t exist in the S3 bucket. Please let me know if you have any follow-up questons.
Respectfully, I would disagree with that assessment of the intention of the dryrun flag, specifically as it relates to most every other AWS service and their CLI commands (at least that I've dealt with). When you run a dry run as part of any CRUD action against VPCs, EC2 instances, route tables, subnets, iam groups/roles, etc.... they all check against IAM permissions.
Granted, I don't expect a change of position here, but I wanted to throw this out as my specific use case is that I am running commands with the specific intention to validate that the IAM permissions are set properly for a given user. The entire purpose of my use case is to 'check' if the user can or cannot run a particular action without actually running the action. I do this through a CI/CD pipeline as an automated check against changes to the environment.
Activity
RyanFitzSimmonsAK commentedon Dec 22, 2025
Hi @berky2755, thanks for reaching out. I was able to reproduce the behavior you observed.
I'll bring this up for review with the team and let you know when I have any updates.
Fix s3 cp --dryrun to validate bucket access before reporting success
ps06756 commentedon Dec 29, 2025
@RyanFitzSimmonsAK Can you review the above PR, I have included the fix for this issue along with explanation about the options considered.
Let me know your thoughts
RyanFitzSimmonsAK commentedon Jan 6, 2026
Hi @ps06756, thanks for your patience. After reviewing with the team, we've agreed not to make changes to the implementation.
--dryrunisn't really intended to validate IAM permissions. Instead, it's meant to communicate what operations would be ran assuming permissions exist. The download implementation needs aHeadObjectoperation because without it, the CLI would always claim that as3://mybucket/object -> ./objectoperation will happen, even ifobjectdoesn’t exist in the S3 bucket. Please let me know if you have any follow-up questons.berky2755 commentedon Jan 7, 2026
Hi @RyanFitzSimmonsAK
Respectfully, I would disagree with that assessment of the intention of the dryrun flag, specifically as it relates to most every other AWS service and their CLI commands (at least that I've dealt with). When you run a dry run as part of any CRUD action against VPCs, EC2 instances, route tables, subnets, iam groups/roles, etc.... they all check against IAM permissions.
Granted, I don't expect a change of position here, but I wanted to throw this out as my specific use case is that I am running commands with the specific intention to validate that the IAM permissions are set properly for a given user. The entire purpose of my use case is to 'check' if the user can or cannot run a particular action without actually running the action. I do this through a CI/CD pipeline as an automated check against changes to the environment.
Thanks for looking into this.