Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
FREEDOM251

Freedom251 › Blog › AccessDenied

How to Fix “S3 PutObject Access Denied” (403): A Complete AWS Troubleshooting Guide

By Freedom251 Team · · 12 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

An Amazon S3 PutObject 403 means AWS denied the specific write request. The fastest reliable fix is to trace the exact principal, bucket, object key, request headers, encryption mode, and network path, then check every policy layer that can allow or deny that request. In most cases, the missing permission is s3:PutObject on an object ARN rather than the bucket ARN, an explicit deny or condition is winning, or an optional feature such as ACLs, tags, SSE-KMS, or a VPC endpoint adds another authorization requirement.

What “Access Denied” means for PutObject

PutObject is an authorization decision, not a diagnosis of one particular problem. A request can have an identity policy that appears to allow S3 writes and still receive HTTP 403 because another applicable policy denies it or because the request includes a feature requiring an additional permission.

As an Amazon Associate I earn from qualifying purchases.

The decision is evaluated for one caller and one exact request. The caller might be an IAM user, an assumed-role session, an AWS service role, or a federated principal. The target is not merely a bucket: it includes the bucket, region, access point (if used), and complete object key, including every prefix. Headers for ACLs, object tags, and server-side encryption also affect the decision. Organization controls, permissions boundaries, session policies, endpoint policies, and network conditions can narrow an otherwise broad allow.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • A bucket ARN such as arn:aws:s3:::example-bucket identifies the bucket itself.
  • An object ARN such as arn:aws:s3:::example-bucket/uploads/* identifies objects beneath a prefix.
  • s3:PutObject must be allowed on the object ARN for the key being written; allowing only the bucket ARN does not authorize an object write.

Start with the smallest factual description of the failed call. Do not change several policies at once; doing so can hide the layer that actually caused the denial and often creates excessive permissions.

1. Record the caller and the exact request

Before editing permissions, capture the values below from the application configuration, SDK logs, or the command that failed. An assumed role’s session ARN and account can differ from the human or workload that launched it.

  • Principal: IAM user ARN, role ARN, or assumed-role session ARN, plus the AWS account that owns it.
  • Target: AWS Region, bucket name, complete key (including prefix), and whether an S3 access point is involved.
  • Request options: canned ACL, explicit tagging, server-side encryption headers, multipart upload, or a custom endpoint.
  • Network path: public S3 endpoint, gateway or interface VPC endpoint, source VPC, and endpoint ID.
  • Policy context: whether the bucket and caller are in the same account or organization, and whether a permissions boundary, session policy, SCP, or RCP applies.

For a CLI test, use the same credentials and region as the failing application. Environment variables keep the example reusable without placing credentials in a command line:

export AWS_PROFILE=the-profile-used-by-the-app
export AWS_REGION=the-bucket-region
export BUCKET=the-bucket-name
export KEY=the/exact/key.txt
printf 'permission proben' > /tmp/s3-probe.txt
aws s3api put-object --bucket "$BUCKET" --key "$KEY" --body /tmp/s3-probe.txt --region "$AWS_REGION"

If this minimal call succeeds while the application fails, compare the application’s additional headers and endpoint settings rather than broadening IAM access.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Grant the baseline object permission

The caller needs s3:PutObject on the object resource that includes the key. A least-privilege identity policy for a prefix looks like this:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "s3:PutObject",
    "Resource": "arn:aws:s3:::BUCKET/PREFIX/*"
  }]
}

Replace BUCKET and PREFIX with the real values. If the application writes to the bucket root, the resource can be arn:aws:s3:::BUCKET/*. If it writes several prefixes, list only those object ARNs or use separate statements. A resource ending at the bucket name is not a substitute for the object ARN.

Check the policy attached to the principal that actually made the call. A policy attached to a different user, role, or parent group does not help if the workload is using another assumed role. Also verify that the key is spelled exactly as authorized: S3 keys are case-sensitive, and a missing or extra prefix places the request outside the permitted resource.

3. Add permissions for features the request actually uses

ACL headers

If the client sends an ACL, such as x-amz-acl: bucket-owner-full-control, the caller also needs s3:PutObjectAcl for the same object. Remove the ACL header only as a diagnostic when the bucket’s ownership and policy permit a test without it; do not remove a required ownership control in production.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Object tags

If the request writes tags at upload time, add s3:PutObjectTagging on the object resource. A request that combines an otherwise valid upload with an unauthorized tag operation can fail even though s3:PutObject is allowed.

Multipart uploads

Multipart workflows perform several API calls rather than one. Check permissions for the complete sequence used by the client, and test a single-part upload separately. With SSE-KMS, completion and later reads can additionally require kms:Decrypt, as described below.

4. Inspect every policy layer for allows and explicit denies

An allow must survive all applicable policy boundaries. An explicit deny wins over an allow, and a condition that evaluates false means the statement does not authorize the request.

Policy or control What to inspect Typical reason for a 403
IAM identity policy Action, object ARN, and conditions attached to the actual user or role s3:PutObject targets only the bucket ARN or the wrong prefix
Bucket policy Principal, resource, account, source network, TLS, and encryption conditions An explicit deny or an allow restricted to a different role or account
Access-point policy Access-point name, object path, and principal conditions The request uses an access point whose policy is narrower than the bucket policy
Permissions boundary Whether the boundary permits the S3 action and resource The identity policy allows the write but the boundary caps it
Session policy Policy passed when the role session was created A federated session is narrower than the role’s attached policies
Organizations SCP or RCP Organization-level denies and resource conditions An account-level guardrail blocks S3 writes or the target Region
VPC endpoint policy Allowed principals, actions, buckets, and prefixes The endpoint denies the request before S3 can honor an identity allow
Block Public Access and ownership controls Whether the request relies on public access or an ACL model disabled by the bucket A public or ACL-based pattern conflicts with the bucket’s controls

Search for statements with "Effect": "Deny" and conditions involving the principal ARN, account ID, object prefix, source VPC, VPC endpoint, aws:SecureTransport, encryption headers, or required tags. A deny that applies to every principal except a short allow-list will also affect an otherwise authorized role.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

5. Check the bucket and access-point policy

Resource policies are especially important for cross-account writes. A bucket policy can allow a role in another account to write only to a defined prefix:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "AllowPartnerPrefixUpload",
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::111122223333:role/UploadRole"},
    "Action": "s3:PutObject",
    "Resource": "arn:aws:s3:::BUCKET/incoming/*"
  }]
}

Adapt the account ID, role name, bucket, and prefix. If the caller sends an ACL, add s3:PutObjectAcl to the action list and make sure the ownership model supports that ACL. If the policy requires a particular encryption header, the client must send exactly that value; a missing or different header causes the condition to fail.

When an access point is used, inspect both the access-point policy and the underlying bucket policy. The ARN and request host differ from a direct bucket request, so a statement written only for the bucket path may not match the access-point request.

6. Resolve cross-account upload failures

For a cross-account upload, authorization commonly has two independent sides: the caller’s account must authorize the role session, and the bucket owner’s resource policy must trust that principal and resource. Confirm all of the following:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. The caller is the intended role session, not a similarly named role in another account.
  2. The role’s identity policy allows s3:PutObject on the exact bucket-and-prefix object ARN.
  3. The bucket policy names the correct role ARN and object resource.
  4. Any ACL requirement is satisfied with s3:PutObjectAcl, or the bucket uses bucket-owner-enforced Object Ownership and the client does not send an incompatible ACL.
  5. If SSE-KMS is used, the KMS key policy and caller IAM policy authorize the required KMS operations across both accounts.
  6. No SCP, RCP, permissions boundary, session policy, endpoint policy, or explicit deny blocks the request.

The AWS-managed aws/s3 KMS key cannot provide cross-account default encryption. A customer-managed KMS key with a policy that trusts the uploading principal is required for that topology.

7. Verify SSE-KMS permissions and encryption conditions

Server-side encryption with AWS KMS keys adds a second authorization system. For an SSE-KMS upload, the caller generally needs kms:GenerateDataKey. Multipart completion or later operations can also require kms:Decrypt. Both the caller’s IAM identity policy and the customer-managed KMS key policy must authorize the operation.

KMS actions cannot be granted through an S3 bucket policy. Add them to the caller’s IAM policy and authorize the principal in the key policy (or through a permitted KMS grant). Scope the permissions to the specific key where practical:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["kms:GenerateDataKey", "kms:Decrypt"],
    "Resource": "arn:aws:kms:REGION:ACCOUNT:key/KEY-ID"
  }]
}

Use the exact Region and key ARN. A bucket policy condition requiring s3:x-amz-server-side-encryption or s3:x-amz-server-side-encryption-aws-kms-key-id must match the headers sent by the SDK. Conversely, if the application sends an SSE-KMS header but the key policy does not trust its role, S3 can return AccessDenied even though the S3 action is allowed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For cross-account encryption, grant the principal in the key policy owned by the key’s account and in the uploading role’s IAM policy. Check key state, Region, and grants as well as policy text. Do not “fix” a KMS denial by silently removing required encryption; that changes the bucket’s security control rather than repairing authorization.

8. Check Object Ownership and ACL behavior

With S3 Object Ownership set to Bucket owner enforced, ACLs are disabled. Requests that attempt to set an ACL other than the permitted bucket-owner-full-control behavior can fail because the bucket no longer accepts ACL management. Remove unnecessary ACL headers and rely on the ownership setting.

In an ACL-enabled cross-account configuration, the bucket owner may require the uploader to send the bucket-owner-full-control canned ACL. That request needs both the ACL header and s3:PutObjectAcl. The bucket policy must allow the principal and the object path, and the object owner result should match the intended access model.

Determine the ownership mode before changing permissions. Adding ACL permissions to a bucket-owner-enforced bucket does not solve an incompatible request; changing ownership mode solely to accommodate an old client can create a broader access-management burden.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

9. Investigate network and organization controls

VPC endpoint policies

A gateway or interface VPC endpoint can impose its own allow-list. Inspect the endpoint policy for the S3 action, bucket ARN, object prefix, and principal. A restrictive endpoint policy can deny a request even when IAM and the bucket policy look correct. Compare the failing application’s route with the successful CLI test; they may use different endpoints.

Conditions on source and transport

Bucket and identity policies often require a particular source VPC, VPC endpoint, account, or secure transport. Verify the request context actually contains the expected values. A condition on aws:SourceVpce, for example, will not match traffic that leaves through a different endpoint or a public S3 path.

Organizations controls

Ask the organization administrator to inspect SCPs and resource control policies for denies affecting S3, KMS, the account, or Region. These controls are outside the bucket and role documents, so editing those documents cannot override an organization-level deny.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

10. Use the error message and CloudTrail to identify the denying layer

Same-account and same-organization requests may return enhanced AccessDenied text that identifies the policy type or ARN responsible. Read the complete error, including any named principal, condition, or policy. Cross-account requests outside the organization and directory-bucket requests may return only generic AccessDenied, so do not assume that a short message means IAM is the only suspect.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Correlate the request with CloudTrail data events for the bucket. Match event time, principal ARN, bucket, key, source IP or VPC endpoint, and encryption fields. Then inspect the bucket policy, access-point policy, endpoint policy, boundaries, session policy, SCP/RCP, and KMS key policy that applied at that time. CloudTrail confirms what was called and by whom; it does not replace reviewing every policy that can deny the call.

11. Retest safely with the smallest request

  1. Use the exact failing principal, Region, bucket, and key prefix.
  2. Run a single-part PutObject without optional ACL and tag headers, only if the bucket policy allows such a test.
  3. Keep required TLS, network, and encryption controls in place; do not disable them merely to obtain a success response.
  4. If the minimal request succeeds, add back one feature at a time: ACL, tags, SSE-KMS, multipart behavior, and finally the production endpoint.
  5. After the cause is found, narrow the policy to the required object prefix, principal, key, and conditions. Remove temporary broad allows and test credentials.

A successful probe proves only that that exact principal and request were authorized. It does not prove that every application role, prefix, Region, or encryption key is configured correctly.

Common failure patterns and their precise fixes

“I have s3:PutObject, but it still returns 403”

Inspect the resource in the statement first. If it ends at arn:aws:s3:::BUCKET, change it to the object ARN matching the key. Then search all policy layers for an explicit deny or a condition that excludes the request.

The upload works without encryption but fails with SSE-KMS

Keep the required encryption setting and authorize kms:GenerateDataKey in the caller’s IAM policy and KMS key policy. Add kms:Decrypt where the multipart or read path needs it, and verify the key ARN and Region.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A cross-account uploader is denied

Validate the role ARN on both sides, the bucket policy’s object resource, and any ACL or ownership requirement. Then check the customer-managed KMS key policy and organization or endpoint controls. The AWS-managed aws/s3 key is not a cross-account solution for default encryption.

The application fails but a basic CLI command works

Compare headers and transport. The application may add an ACL, tags, SSE-KMS, multipart calls, or a VPC endpoint that the CLI probe did not use. Grant only the additional action required by that feature.

The error names no policy

Generic text is expected for some cross-account and directory-bucket requests. Use CloudTrail and review every applicable layer rather than relying on the message to identify the deny.

Final least-privilege checklist

  • Principal ARN and account are confirmed from the failing request.
  • s3:PutObject targets the exact object ARN and prefix.
  • s3:PutObjectAcl is present only when an ACL is sent and supported.
  • s3:PutObjectTagging is present only when upload-time tags are written.
  • Bucket or access-point policy trusts the correct principal and key path.
  • No explicit deny or unmet condition exists in IAM, resource, endpoint, boundary, session, SCP/RCP, or Block Public Access controls.
  • SSE-KMS requests have the required KMS permissions in both IAM and the customer-managed key policy.
  • Object Ownership and ACL behavior match the client’s headers and cross-account design.
  • The final test uses the production principal, network path, encryption, and request shape.

If you prefer an automated Windows maintenance shortcut while investigating local tooling or environment issues, Outbyte PC Repair can check common system problems, tune resource-heavy settings, clean temporary and cache files, and provide crash logs. It complements antivirus software rather than replacing it; results vary and no tool repairs every crash. It runs on Windows 11, 10, 8, and 7, with a category-limited free trial of at least two days before a subscription.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

AccessDeniedAmazon S3AWS IAMcloud securityPutObjectSSE-KMSVPC endpoints

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.