A public EBS snapshot lets any AWS account on Earth copy your disk data and read whatever was on it. Strip the public createVolumePermission immediately and audit who copied it before you assume it was harmless.
EBS snapshots are point-in-time copies of your block storage volumes. They hold exactly what was on the disk at the moment the snapshot was taken: application data, config files, credentials baked into AMIs, database files, and anything else that happened to be on the volume. When a snapshot is marked public, you are not exposing a link or a thumbnail. You are handing out the raw contents of a disk to the entire AWS customer base.
This check flags any EBS snapshot whose createVolumePermission is set to public, meaning any AWS account can create a volume from it and mount the data.
What this check detects
Every EBS snapshot has a set of permissions that control who can create volumes from it. By default, a snapshot is private to the account that owns it. You can share it with specific account IDs, or you can set it to public, which adds the special all group to the create-volume permission list.
The ebs_snapshotpublic check inspects the createVolumePermission attribute of each snapshot in every region and reports any snapshot where that group includes all. In plain terms: it finds snapshots that anyone with an AWS account can clone.
Note: Public sharing is not the same as making a snapshot available across your own organization. Sharing with specific account IDs (or via AWS RAM) keeps the snapshot private to those accounts. Public means the global all group, with no restriction on who copies it.
You can confirm the state of a single snapshot yourself:
aws ec2 describe-snapshot-attribute \
--snapshot-id snap-0123456789abcdef0 \
--attribute createVolumePermission \
--region us-east-1
If the output contains a CreateVolumePermissions entry with "Group": "all", the snapshot is public.
Why it matters
The risk here is not theoretical. Public snapshots are one of the most reliable sources of leaked cloud data, because they are trivial to find at scale and they often contain far more than people expect.
The data is usually richer than the owner thinks
A snapshot of a root volume frequently includes things nobody intended to publish:
- Hardcoded credentials in application config,
.envfiles, or shell history - SSH private keys left in
~/.sshor in deployment tooling - Database files from local SQLite, MySQL, or PostgreSQL data directories
- Cloud credentials in
~/.aws/credentialsor instance metadata caches - Source code and internal documentation that maps out the rest of your infrastructure
The attack is cheap and automated
An attacker does not need access to your account. They run their own. Public snapshots can be enumerated through describe-snapshots with --restorable-by-user-ids all, copied into the attacker's account, mounted, and searched offline at leisure. Tools built for exactly this purpose have existed for years. Once a snapshot is public, assume it has been indexed.
Danger: If a snapshot has been public for any length of time, treat the data on it as compromised. Rotate any credentials, keys, or tokens that could have lived on that volume. Removing the public permission does not undo copies that already happened.
It rarely happens on purpose
Most public snapshots are accidents: a developer testing AMI sharing, a copy-paste from a tutorial, a Terraform module with a wide-open permission block, or an AMI that was made public and dragged its backing snapshots along with it. The intent does not matter to the outcome.
How to fix it
The fix is to remove the public permission so the snapshot reverts to private. This is a fast, low-risk change for the snapshot itself, but read the danger callout above first, because the data exposure may already have happened.
Option 1: AWS CLI
Reset the create-volume permission to private:
aws ec2 reset-snapshot-attribute \
--snapshot-id snap-0123456789abcdef0 \
--attribute createVolumePermission \
--region us-east-1
Or remove the public group explicitly while leaving any intentional account-level shares intact:
aws ec2 modify-snapshot-attribute \
--snapshot-id snap-0123456789abcdef0 \
--create-volume-permission "Remove=[{Group=all}]" \
--region us-east-1
Verify it took effect:
aws ec2 describe-snapshot-attribute \
--snapshot-id snap-0123456789abcdef0 \
--attribute createVolumePermission \
--region us-east-1
An empty CreateVolumePermissions list means the snapshot is private again.
Option 2: AWS Console
- Open the EC2 console and go to Elastic Block Store → Snapshots.
- Select the snapshot, then choose Actions → Modify permissions.
- Set the permission to Private.
- Remove any unintended account IDs from the shared list while you are there.
- Save.
Warning: If the public snapshot backs a public AMI, removing the snapshot permission can break the AMI for legitimate users who relied on it. Check whether the snapshot is referenced by a shared AMI first with aws ec2 describe-images --filters "Name=block-device-mapping.snapshot-id,Values=snap-...", and make the AMI private too if it was not meant to be shared.
Find every public snapshot in an account
Before you fix one, find them all. This lists snapshots your account owns that are publicly restorable:
for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
echo "Region: $region"
aws ec2 describe-snapshots \
--owner-ids self \
--restorable-by-user-ids all \
--region "$region" \
--query 'Snapshots[].SnapshotId' \
--output text
done
Tip: Wrap the loop above in a script that pipes each snapshot ID straight into reset-snapshot-attribute. For a one-time cleanup across an account, that turns a tedious manual hunt into a single run. Just log every change so you have a record of what was made private and when.
How to prevent it from happening again
Fixing the snapshots you have today does nothing to stop the next one. Prevention belongs in three places: account controls, infrastructure code, and continuous monitoring.
Block public sharing at the account level
AWS provides an account-wide setting that blocks public sharing of new EBS snapshots. Enable it per region:
aws ec2 enable-snapshot-block-public-access \
--state block-all-sharing \
--region us-east-1
With block-all-sharing, snapshots already public stay public until you reset them, but no new snapshot can be made public. Use block-new-sharing if you need existing public snapshots to remain reachable while preventing future ones. Confirm the state:
aws ec2 get-snapshot-block-public-access-state --region us-east-1
Note: This setting is regional. You need to enable it in every region you operate in, and ideally in every region you do not, since accidental snapshots can land anywhere. Roll it out with a script that loops over describe-regions.
Guard it in infrastructure as code
If you manage snapshots or AMIs in Terraform, never set a snapshot create-volume permission to the all group. For AMI sharing, share with explicit account IDs rather than making the AMI public:
// Terraform: share with specific accounts, never "all"
resource "aws_ami_launch_permission" "shared" {
image_id = aws_ami.app.id
account_id = "111122223333"
}
Add a policy-as-code gate
Catch the misconfiguration before it merges. An OPA or Conftest rule against your Terraform plan can fail the build if anything tries to share publicly:
# Conftest example: deny public snapshot or AMI sharing
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_snapshot_create_volume_permission"
resource.change.after.group == "all"
msg := sprintf("Public snapshot sharing not allowed: %s", [resource.address])
}
Detect drift continuously
Click-ops changes and out-of-band scripts bypass your IaC gates entirely. Continuous detection closes that gap. The Lensix ebs_snapshotpublic check runs across all regions and accounts, so a snapshot made public through the console at 2am still surfaces as a finding. AWS Config managed rules and EventBridge rules on ModifySnapshotAttribute events are useful complements for near-real-time alerting.
Best practices
- Default to private, share explicitly. When you genuinely need to share a snapshot, share with named account IDs. There is almost never a legitimate reason to use the public
allgroup. - Encrypt your snapshots. Encrypted snapshots cannot be shared publicly at all, because the recipient would need your KMS key. Encryption gives you a hard structural barrier against this entire class of mistake.
- Keep secrets off your disks. The damage from a public snapshot comes from what was on the volume. Use IAM roles instead of stored credentials, pull secrets from Secrets Manager or Parameter Store at runtime, and avoid baking anything sensitive into AMIs.
- Audit AMI sharing alongside snapshots. A public AMI exposes its backing snapshots. Review both together rather than treating them as separate problems.
- Enable block-public-access everywhere by default. Make the account-level block the baseline for every region in every account, then carve out narrow exceptions only when a real business case exists.
- Treat exposure as an incident, not a fix. Removing the public flag closes the door. It does not tell you who walked through it. Rotate anything that may have been exposed and check CloudTrail for
CreateVolumeor copy activity from unfamiliar accounts.
Public EBS snapshots are one of the highest-signal findings in any cloud audit. They are easy to create by accident, trivial for attackers to exploit, and simple to prevent once you put the account-level block and a policy gate in place. Fix the ones you have, then make new ones structurally impossible.

