Back to blog
AWSBest PracticesCloud SecurityOperations & ComplianceStorage

Fixing Unencrypted EBS Volumes on AWS

Learn why unencrypted EBS volumes are a real risk, how to encrypt them step by step, and how to enforce EBS encryption by default with SCPs and CI gates.

TL;DR

This check flags EBS volumes attached to your EC2 instances that are not encrypted at rest, leaving snapshots and underlying disk data exposed if AWS storage or a stolen snapshot is ever accessed. You cannot encrypt a volume in place, so the fix is to snapshot, copy with encryption, and swap the volume. Turn on account-level EBS encryption by default to stop it recurring.

Encryption at rest is one of those controls that costs almost nothing to enable and quietly closes off a whole class of data exposure scenarios. Yet unencrypted EBS volumes remain one of the most common findings in AWS accounts, usually because encryption by default was never switched on and someone launched an instance from an unencrypted AMI years ago.

This post walks through what the ec2_unencrypted_volumes check looks for, why it matters more than people assume, and exactly how to remediate it without losing data.


What this check detects

The Lensix Unencrypted EBS Volumes check inspects every EBS volume attached to an EC2 instance and reports any where the Encrypted attribute is false. It runs as part of the ec2_checks module and fails for an instance if one or more of its attached volumes (root or data) is unencrypted.

EBS encryption uses AES-256 and integrates with AWS KMS. When a volume is encrypted, the following are all encrypted automatically:

  • Data at rest inside the volume
  • Data moving between the volume and the instance
  • Snapshots created from the volume
  • Volumes created from those snapshots

Note: Encryption status is set at volume creation and cannot be changed afterward. There is no "encrypt this volume" button. That is why remediation involves creating a new encrypted volume rather than flipping a flag.


Why it matters

The instinctive pushback is "the data never leaves AWS, so who is going to read the raw disk?" That reasoning misses where the real risk lives.

Snapshots travel further than volumes

An unencrypted volume produces unencrypted snapshots. Snapshots get copied across regions, shared with other accounts, and occasionally made public by mistake. A public unencrypted snapshot is a full copy of your disk that anyone can mount. There is a long history of breaches that started with exactly this: a snapshot shared too broadly, containing credentials, customer records, or private keys.

Warning: You cannot share an encrypted snapshot publicly, and sharing it with another account requires sharing the KMS key too. Encryption is not just data protection, it is a guardrail against accidental over-sharing.

Compliance frameworks expect it

PCI DSS, HIPAA, SOC 2, and most internal security baselines treat encryption at rest as a hard requirement. An unencrypted volume holding cardholder data or PHI is a finding an auditor will write up, and remediating during an audit window is far more stressful than handling it now.

Defense in depth

If an attacker compromises AWS credentials with EC2 permissions, they may try to create and export snapshots. Encryption combined with restricted KMS key policies adds another layer they have to defeat. It is not a silver bullet, but it raises the cost of exfiltration.


How to fix it

Since encryption cannot be added in place, the remediation flow is: snapshot the volume, copy the snapshot with encryption enabled, create a new encrypted volume, then swap it onto the instance. Below is the manual process for a single volume.

Step 1: Find the unencrypted volumes

aws ec2 describe-volumes \
  --filters Name=encrypted,Values=false \
  --query "Volumes[].{ID:VolumeId,AZ:AvailabilityZone,Instance:Attachments[0].InstanceId}" \
  --output table

Step 2: Snapshot the unencrypted volume

aws ec2 create-snapshot \
  --volume-id vol-0abc123def456 \
  --description "pre-encryption snapshot"

Wait for the snapshot to reach the completed state:

aws ec2 wait snapshot-completed --snapshot-ids snap-0aaa111bbb222

Step 3: Copy the snapshot with encryption enabled

aws ec2 copy-snapshot \
  --source-region us-east-1 \
  --source-snapshot-id snap-0aaa111bbb222 \
  --encrypted \
  --kms-key-id alias/aws/ebs \
  --description "encrypted copy"

Tip: Use a customer-managed KMS key instead of the default alias/aws/ebs key. Customer-managed keys let you control the key policy, enable rotation on your own schedule, and produce CloudTrail records of every decrypt call, which is invaluable during an investigation.

Step 4: Create an encrypted volume from the new snapshot

aws ec2 create-volume \
  --snapshot-id snap-0encrypted333 \
  --availability-zone us-east-1a \
  --volume-type gp3 \
  --query VolumeId --output text

Step 5: Swap the volume on the instance

Danger: Detaching the root volume requires stopping the instance, and detaching any volume risks data loss if the application is still writing to it. Stop the instance or quiesce the application first, and confirm you have a working snapshot before you detach anything.

Stop the instance, detach the old unencrypted volume, and attach the new encrypted one using the same device name:

# Stop the instance
aws ec2 stop-instances --instance-ids i-0instance123
aws ec2 wait instance-stopped --instance-ids i-0instance123

# Detach the old volume
aws ec2 detach-volume --volume-id vol-0abc123def456

# Attach the new encrypted volume at the same device path
aws ec2 attach-volume \
  --volume-id vol-0newencrypted \
  --instance-id i-0instance123 \
  --device /dev/xvda

# Start the instance back up
aws ec2 start-instances --instance-ids i-0instance123

Once you confirm the instance is healthy and the data is intact, delete the old unencrypted volume and its unencrypted snapshot so they do not linger as a liability.

Warning: Snapshots and orphaned volumes still cost money and still count as unencrypted data. After a successful swap, clean up the old snap- and vol- resources, or they will show up in the next audit anyway.


How to prevent it from happening again

Manual remediation is fine for a handful of volumes, but the real win is making it impossible to create an unencrypted volume in the first place.

Turn on EBS encryption by default

This single setting forces every new volume in a region to be encrypted, with no change required to your launch templates or pipelines. It is per-region, so apply it everywhere you operate.

aws ec2 enable-ebs-encryption-by-default --region us-east-1

# Verify
aws ec2 get-ebs-encryption-by-default --region us-east-1

Note: Encryption by default applies to newly created volumes only. Existing unencrypted volumes are unaffected, so you still need to remediate the ones the check already found.

Enforce it with an SCP

For multi-account setups, a Service Control Policy stops anyone from disabling encryption by default or launching unencrypted volumes, even with admin rights inside the account:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnencryptedEbs",
      "Effect": "Deny",
      "Action": "ec2:CreateVolume",
      "Resource": "*",
      "Condition": {
        "Bool": { "ec2:Encrypted": "false" }
      }
    }
  ]
}

Bake it into your IaC

If you provision with Terraform, set encryption explicitly so the intent is visible in code review and drift detection catches any change:

resource "aws_ebs_volume" "data" {
  availability_zone = "us-east-1a"
  size              = 100
  type              = "gp3"
  encrypted         = true
  kms_key_id        = aws_kms_key.ebs.arn
}

resource "aws_instance" "app" {
  ami           = var.ami_id
  instance_type = "t3.medium"

  root_block_device {
    encrypted   = true
    kms_key_id  = aws_kms_key.ebs.arn
    volume_type = "gp3"
  }
}

Gate it in CI/CD

Run a static analysis tool against your Terraform or CloudFormation before it merges. Both tfsec and checkov ship with rules for unencrypted EBS volumes out of the box:

# Fails the build if an unencrypted EBS volume is defined
checkov -d . --check CKV_AWS_3,CKV_AWS_189

Tip: Layer your defenses. Encryption by default handles humans who forget, the SCP handles humans who try to bypass it, and the CI gate catches it before anything even reaches AWS. Any one of these alone has gaps.


Best practices

  • Use customer-managed KMS keys for anything sensitive, so you control the key policy and get full CloudTrail visibility into decrypt operations.
  • Enable encryption by default in every region, including ones you do not actively use, to stop shadow workloads from creating unencrypted volumes.
  • Encrypt your AMIs. If you launch from a custom AMI, make sure its snapshots are encrypted, otherwise every instance inherits an unencrypted root volume.
  • Restrict snapshot sharing with an SCP that denies ec2:ModifySnapshotAttribute for public sharing, closing the accidental-exposure path entirely.
  • Rotate KMS keys annually, which is automatic for customer-managed keys when you enable rotation.
  • Re-scan regularly. Encryption by default does not fix existing volumes, so keep this check running until your fleet reports clean.

Encryption at rest is the kind of control that should be invisible once it is set up. Flip the account default, enforce it with policy, and gate it in your pipeline, then the only unencrypted volumes you will ever see are the legacy ones you are actively cleaning up.