All resources
// Resources

AWS S3 Security Review: Public Access to Evidence

Published July 16, 2026

S3 review begins with access outcome, not bucket-policy syntax. Object access can be affected by identity policies, bucket and access-point policies, ACLs, Object Ownership, and Block Public Access (BPA). A successful GetObject or PutObject should be explainable from a named principal, an intended object prefix, and recorded evidence.

Set account and bucket guardrails

Enable all four BPA settings at account level unless a documented, tested requirement prevents it: BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, and RestrictPublicBuckets. AWS applies the most restrictive applicable combination across organization, account, bucket, and access point. BPA does not rewrite existing policies or ACLs; removing it can reactivate a public policy or ACL. Check account and bucket configuration, then inspect every exception.

Use Object Ownership BucketOwnerEnforced for normal workloads. It is default for new buckets, disables ACLs, and makes bucket owner own every object. Uploads without an ACL or with bucket-owner-full-control remain accepted; other ACL-bearing uploads can fail. Before changing an existing bucket, inventory object ACL dependencies and policy conditions. Do not retain ACLs because they are familiar: use bucket or access-point policies when policy-wide control is sufficient.

Test policy paths

Bucket policies should name fixed principals, actions, resources, and conditions. Access points can narrow network or application access, but have their own policy and BPA evaluation. Review both access-point and underlying bucket policy. A policy with Principal: "*" is not made safe by an undocumented network assumption.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "TenantAReadOnly",
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::111122223333:role/tenant-a-app"},
    "Action": ["s3:GetObject"],
    "Resource": "arn:aws:s3:::example-private/tenant-a/*"
  }]
}

Test allowed read, forbidden sibling-prefix read, list behavior, cross-account principal, and policy update attempt. For upload paths, confirm required server-side encryption and destination prefix separately. CloudTrail management events show bucket configuration activity, but S3 object operations are data events and are not logged by default. Enable selectors for critical buckets or prefixes; scope deliberately because data events can be high volume and charged.

Treat presigned URLs as bearer access

A presigned URL uses credentials of its generator to give time-limited access to a specified S3 operation. Anybody holding it can use it until expiry, so never place it in tickets, logs, or public telemetry. Generate server-side for one object and one operation, use shortest practical expiry, and verify the signer has no unintended broad access. Console-generated URLs expire within 12 hours; AWS CLI presigning can use up to seven days, but product policy may require far less.

For presigned PUT, construct object key server-side, require expected content constraints where supported by signing, and record issuer, target bucket/key, operation, expiry, request ID, and correlation ID without storing full URL query strings. Test expired URL, changed key, changed method, and unauthorized caller. Revoke underlying credentials or change authorization when urgent containment is required; expiry alone is not an incident plan.

Completed artifact and decision

ControlEvidence fieldOwnerPass/failExceptionRemediation
Account BPAaccount ID, four settings, capture timecloud platform ownerpass/failapproved public workload, expiryenable missing setting or isolate workload
Object Ownershipbucket, ownership mode, ACL inventorystorage ownerpass/failmigration dependency, expirymigrate ACL grants to policy
Resource policiespolicy version, principal/prefix test outputservice ownerpass/failcross-account contractremove wildcard or narrow condition
Data eventstrail selector, bucket/prefix, sample eventsecurity ownerpass/failcost-approved gapadd focused selector

Public delivery, website hosting, replication, and partner upload may be valid needs. Each needs named owner, exact bucket/prefix, compensating controls, expiry, and retest. “Public because application needs it” is not an exception record. Infrastructure testing can review approved S3 controls.

Worked case: presigned intake upload

Issue one short-lived PUT URL for a test object whose key is generated server-side. Sign required content type and checksum headers, then upload correct fixture. Expected output is object at assigned key and intake record marked pending inspection, not approved for downstream use. Retry with different content type, altered signed header, oversized fixture, expired URL, and reused URL; each must produce rejection or remain unavailable according to documented intake workflow. A signed URL is bearer access bounded by its signer permissions and lifetime; validation, size policy, type validation, and malware scanning remain application controls around upload.

Run Access Analyzer review for bucket policy and access points, then investigate every external finding against intended principals. For an approved external exception, record owner, exact scope, expiry, and independent verifier. At expiry, verifier confirms access no longer works from external test principal and attaches result to exception record. Closure evidence includes policy revision, analyzer output, upload test matrix, scanner disposition, and external-expiry result. Do not infer safety from encryption or a non-public console label.

Sources

Worked closure check

For document-storage review, close against bucket ARN, account, policy revision, BPA state, ownership mode, and sampled principal outcome. Name storage owner and retain CloudTrail selector or test transcript with decision record. These artifacts describe access tested on that date, not cloud compliance, certification, or legal sufficiency. Reopen result after policy, ACL, access-point, or presigned-upload design changes. Independent reviewer should attempt one forbidden sibling-prefix read and trace denial through applicable policy evaluation; unresolved external access stays visible.

Have a system that needs testing?