Skip to content
Free tool · no signup

S3 Bucket Policy Auditor

Answer the question “is my S3 bucket public?” without touching AWS. Paste an S3 bucket policy JSON (and, if you have it, a Public Access Block config) and get severity-ranked findings for anonymous access, public read / write / delete, missing TLS enforcement, overly broad s3:*, and conditions that only look restrictive. Everything is parsed in your browser; nothing is uploaded and no bucket is ever contacted.

Runs locally — nothing is uploaded. Your policy is parsed in your browser with JSON.parse. This tool never contacts AWS and never probes, lists or fetches any bucket.

Bucket policy JSON *
Public Access Block config (optional)
TL;DR

What this tool is

  • Paste an S3 bucket policy JSON — and, optionally, a Public Access Block configuration — and get severity-ranked findings for public exposure and common misconfigurations.
  • Flags anonymous access (Principal "*" or {"AWS":"*"} with Effect Allow and no restricting Condition), public read (s3:GetObject), and public write/delete (s3:PutObject / s3:DeleteObject) — the three ways a bucket leaks or gets tampered with.
  • Catches the subtle mistakes too: no aws:SecureTransport deny (traffic allowed over plain HTTP), overly broad s3:* actions, and Conditions that look restrictive but are not — such as aws:Referer, which an attacker can spoof.
  • If you paste a Public Access Block config, it tells you whether BlockPublicPolicy / RestrictPublicBuckets would override a public policy — the account- or bucket-level backstop that AWS evaluates before the policy.
  • Runs entirely in your browser. The policy JSON is parsed locally with JSON.parse — nothing is uploaded, and the tool never contacts AWS or probes any bucket.

How S3 decides who can reach a bucket

An S3 bucket policy is a resource-based IAM policy attached to the bucket. Each statement has an Effect (Allow or Deny), a Principal (who it applies to), an Action (which S3 API calls), a Resource (the bucket and/or its objects), and an optional Condition. A request is allowed only if some statement allows it and no statement denies it, after AWS first applies Block Public Access.

The three ways a policy goes public

  • Anonymous Principal. "Principal": "*" or {"AWS":"*"} on an Allow means any unauthenticated caller on the internet. Unless a Condition truly narrows it, that statement is open to the world.
  • Public read. s3:GetObject to * lets anyone download every object — the classic data-leak pattern behind countless breaches.
  • Public write / delete. s3:PutObject or s3:DeleteObject to * lets strangers overwrite, defacing, or ransom your data — tampering, not just exposure.

Conditions that do not restrict

A Condition only narrows access if it scopes by something the caller cannot forge — network (aws:SourceIp, aws:SourceVpc, aws:SourceVpce) or identity (aws:SourceArn, aws:PrincipalOrgID). A Condition on aws:Referer or aws:UserAgent is not a boundary — both headers are set by the client and spoofed in one line. The auditor treats a public Principal guarded only by such a Condition as still public.

Block Public Access — the backstop

AWS evaluates Block Public Access (BPA) before the policy. With BlockPublicPolicy enabled, S3 rejects any attempt to set a policy that grants public access; with RestrictPublicBuckets enabled, an already-public policy is neutralised so only AWS service principals and authorised users get through. Paste your Public Access Block config and the auditor will tell you whether these would override a public policy — but note BPA and the policy are separate controls: a public policy with BPA off is live exposure.

Reading a finding: each result carries a severity, the statement it came from, the plain-English risk (data exposure vs. data tampering), and the concrete fix. Public read is a confidentiality failure; public write or delete is an integrity failure and is usually worse. A clean result means this policy has no flagged patterns — it is not a full security attestation, since ACLs, IAM identity policies and account-level BPA are not part of the policy document.

S3 Bucket Policy Auditor — animated demo
A quick look at S3 Bucket Policy Auditor — it runs entirely in your browser.

Frequently asked questions

What makes an S3 bucket "public"?

A bucket is reachable by anonymous callers when a bucket policy statement has Effect "Allow", a Principal of "*" (or {"AWS":"*"}), and no Condition that actually restricts who can call it. AWS also evaluates Block Public Access settings first: if BlockPublicPolicy or RestrictPublicBuckets is enabled at the bucket or account level, a public policy is rejected or neutralised regardless of what the policy says. This tool flags the policy-level exposure and, when you also paste a Public Access Block config, tells you whether that backstop would override it. Object ACLs and account-level settings are not visible in a policy JSON, so they are out of scope here.

Does this tool connect to AWS or read my actual bucket?

No. It never makes a network call and never contacts AWS. You paste the policy JSON and the config JSON, and everything is parsed and analysed locally in your browser with JSON.parse — the same way a text editor opens a file. It cannot and does not probe, list, or fetch anything from a real bucket, so running it leaks nothing and carries no risk of triggering access logs or alarms on your account. That also means it only sees what you paste: it reasons about the policy document, not the live state of the bucket.

Why does a Condition like aws:Referer not count as a real restriction?

The HTTP Referer header is set by the client and is trivially forged with a single curl or script line, so a policy that only allows access "when aws:Referer equals my-site.com" grants that access to anyone willing to send that header — which is everyone. The same applies to aws:UserAgent. These were historically used as cheap hotlink protection and are still common in copy-pasted policies, but they provide no security boundary. Real restrictions scope access by network or identity: aws:SourceIp, aws:SourceVpc / aws:SourceVpce, aws:SourceArn, aws:PrincipalOrgID, or an access-point condition. The auditor treats a public Principal guarded only by a spoofable Condition as still public, and flags the ineffective Condition separately.

What is the aws:SecureTransport check and why does it matter?

aws:SecureTransport is true when a request arrives over TLS (HTTPS) and false over plain HTTP. S3 accepts both unless you forbid the cleartext path, so the recommended control is a Deny statement on s3:* for Principal "*" with a Condition of Bool aws:SecureTransport false, covering both the bucket ARN and its objects (arn:aws:s3:::bucket and arn:aws:s3:::bucket/*). Without it, requests and any credentials or data they carry can traverse the network unencrypted. The auditor scans the whole policy for that Deny and, if it is missing, raises a finding recommending you add it. This is a standard CIS AWS Foundations benchmark expectation.

Is "no findings" a guarantee my bucket is secure?

No. A clean result means the policy JSON you pasted contains no public-exposure or misconfiguration patterns this tool checks for — it is a strong signal, not a certificate. S3 access is the combined result of the bucket policy, object and bucket ACLs, Block Public Access settings (bucket and account), IAM identity policies, VPC endpoint policies, Organizations SCPs, and access points. This tool only sees the policy document (and the Public Access Block config, if you paste it). Treat a clean audit as "this policy is not the problem" and still confirm ACLs are disabled, Block Public Access is on where it should be, and encryption and logging are configured.

🎉 New here? Use code WELCOME10 for 10% off any plan at checkout
S3 Bucket Policy Auditor — Is My S3 Bucket Public? · PlayCISO