📣 Introducing $2.95/Hr H100, H200, B200s, and B300s: train, fine-tune, and scale ML models affordably, without having to DIY the infrastructure   📣 Run Saturn Cloud on AWS, GCP, Azure, Nebius, Crusoe, or on-prem. 📣 Introducing $2.95/Hr H100, H200, B200s, and B300s: train, fine-tune, and scale ML models affordably, without having to DIY the infrastructure   📣 Run Saturn Cloud on AWS, GCP, Azure, Nebius, Crusoe, or on-prem. 📣 Introducing $2.95/Hr H100, H200, B200s, and B300s: train, fine-tune, and scale ML models affordably, without having to DIY the infrastructure   📣 Run Saturn Cloud on AWS, GCP, Azure, Nebius, Crusoe, or on-prem.
← Back to Blog

Access Denied Issues with Cross Account S3 Buckets

Cross account s3 buckets can lead to frustrating permissions issues

Access Denied Issues with Cross Account S3 Buckets

Cross account S3 buckets are pretty important for large organizations, however if managed improperly can cause permissions nightmares. AWS now recommends that S3 buckets be created with ACLs (access control lists) disabled, however older S3 buckets may still have this setting enabled. with ACLs, each object in the S3 bucket can have a different owner (AWS account). If another AWS account is writing to your bucket, you may not have permissions to modify or delete the objects, even if you own the bucket. Newer S3 buckets disable this capability by default which prevents this problem from occuring.

If you’re running into this problem, the following code snippet can help you. We will

  1. Pull data for every object in the S3 bucket
  2. Figure out which AWS accounts own objects in the bucket (represented by the canonical id of the AWS account)
  3. Use those accounts to give control of the objects in S3 back to the owner of the S3 bucket.

The first section inspects every object in the S3 bucket to figure out who the different owners are. The IDs printed are the canonical IDs of the AWS accounts that own the objects.

import boto3
from collections import Counter
bucket = "openproblems-bio"
session = boto3.Session()
client = session.client('s3')
owner_ids = Counter()

data = []
for response in client.get_paginator('list_objects').paginate(Bucket=bucket):
    for obj in response['Contents']:
        owner_id = obj['Owner']['ID']
        key = obj['Key']
        data.append((owner_id, key))

owner_ids.update(x[0] for x in data)
print(owner_ids)

This second snippet will give control for those objects back to the bucket owner.

for owner_id, key in data:
    if owner_id == bad_owner:
        print(f'fixing {key}')
        client.put_object_acl(ACL='bucket-owner-full-control', Bucket=bucket, Key=key)

Afterwards - you can disable ACLs on the bucket to prevent this from happening again

This must be run in the AWS account owning the bucket.

$ aws s3api put-bucket-ownership-controls --bucket BUCKET --ownership-controls="Rules=[{ObjectOwnership=BucketOwnerEnforced}]"

Keep reading

Related articles

Access Denied Issues with Cross Account S3 Buckets
Dec 11, 2025

Choosing an MLOps Platform in 2026

Access Denied Issues with Cross Account S3 Buckets
Dec 10, 2025

SageMaker vs. Saturn Cloud: Which One Is Better for Your Team?

Access Denied Issues with Cross Account S3 Buckets
Dec 1, 2025

Production Inference at Scale with Saturn Cloud & Nebius Token Factory