Skip to content

s3 cp with dryrun flag does not properly check IAM permissions #9935

Open

Description

@berky2755

Describe the bug

the s3 cp command with --dryrun doesn't properly fail when iam permissions don't allow the command. ie...

aws s3 cp {my-local-file} 's3://restricted-bucket/{remote-file}' --dryrun

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

Current Behavior

Upload

$ aws s3 cp {my-local-file} 's3://restricted-bucket/{remote-file}' --dryrun
(dryrun) upload: ./{my-local-file} to s3://restricted-bucket/{remote-file}

$ echo $?
0

$ 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

Additional Information/Context

No response

CLI version used

2.30.4

Environment details (OS name and version, etc.)

AWS Linux 2023.9.20251208

Activity

  1. added
    bugThis issue is a bug.
    needs-triageThis issue or PR still needs to be triaged.
    on Dec 18, 2025
  2. added
    investigatingThis issue is being investigated and/or work is in progress to resolve the issue.
    p2This is a standard priority issue
    needs-reviewThis issue or pull request needs review from a core team member.
    and removed
    needs-triageThis issue or PR still needs to be triaged.
    investigatingThis issue is being investigated and/or work is in progress to resolve the issue.
    on Dec 22, 2025
  3. RyanFitzSimmonsAK commented on Dec 22, 2025

    @RyanFitzSimmonsAK
    Contributor

    Hi @berky2755, thanks for reaching out. I was able to reproduce the behavior you observed.

    C:\Users\rtsfitz\testdirectory>aws s3 cp s3://redacted/test.txt . --profile testUser
    fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
    
    C:\Users\rtsfitz\testdirectory>aws s3 cp s3://redacted/test.txt . --profile testUser --dryrun
    fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
    
    C:\Users\rtsfitz\testdirectory>aws s3 cp test.txt s3://redacted --profile testUser
    upload failed: .\test.txt to s3://redacted/test.txt An error occurred (AccessDenied) when calling the PutObject operation: User: arn:aws:iam::redacted:user/testUser is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::redacted/test.txt" because no identity-based policy allows the s3:PutObject action
    
    C:\Users\rtsfitz\testdirectory>aws s3 cp test.txt s3://redacted --profile testUser --dryrun
    (dryrun) upload: .\test.txt to s3://redacted/test.txt
    

    I'll bring this up for review with the team and let you know when I have any updates.

  4. added a commit that references this issue on Dec 29, 2025
    7f3759b
  5. ps06756 commented on Dec 29, 2025

    @ps06756

    @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

  6. RyanFitzSimmonsAK commented on Jan 6, 2026

    @RyanFitzSimmonsAK
    Contributor

    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.

  7. added
    response-requestedWaiting on additional info and feedback. Will move to "closing-soon" in 7 days.
    and removed
    needs-reviewThis issue or pull request needs review from a core team member.
    on Jan 6, 2026
  8. berky2755 commented on Jan 7, 2026

    @berky2755
    Author

    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 @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.

  9. removed
    response-requestedWaiting on additional info and feedback. Will move to "closing-soon" in 7 days.
    on Jan 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugThis issue is a bug.p2This is a standard priority issues3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions