Security Hub control EC2.3 fails when an EBS volume attached to an EC2 instance is unencrypted. You cannot encrypt an existing EBS volume in place. Snapshot it, create an encrypted volume from that snapshot, and swap it in on the same device name while the instance is stopped. Then enable EBS encryption by default in every Region.
Encryption is one flag on a create call. The real work is the swap: matching the old volume’s settings, getting the root device name right and keeping the old volume until the new one has proven itself.
What the scanner is actually detecting
EC2.3 is a cloud security posture management (CSPM) check. It never looks inside the instance; it reads the volume’s configuration through AWS Config.
| Field | Value |
|---|---|
| Scanner | AWS Security Hub CSPM |
| Finding title | [EC2.3] Attached Amazon EBS volumes should be encrypted at-rest |
| Resource type | AWS::EC2::Volume |
| AWS Config rule | encrypted-volumes |
| Severity and schedule | Medium, change triggered, no parameters |
A volume passes only when it is attached and its Encrypted attribute is true. Unattached volumes are not evaluated. A separate control, [EC2.7] EBS default encryption should be enabled, checks the Region-wide encryption by default setting, and you will usually fix both together.
Real-world risk, stated honestly
EBS encryption uses an AES-256 data key protected by AWS KMS. Per AWS, an encrypted volume protects data at rest, data moving between the volume and the instance, every snapshot taken from it, and every volume restored from those snapshots.
It does not hide data from anyone who can use the running instance. Encryption is transparent to the operating system, so an attacker with a shell or a file-read bug sees plaintext, and an IAM principal with EC2 permissions and use of the key can snapshot the volume and mount a copy.
The practical gains are at the snapshot level. Only unencrypted snapshots can be shared publicly, so encryption removes the accidental public snapshot. Snapshots encrypted with the AWS managed key (aws/ebs) cannot be shared with other accounts at all. AWS maps EC2.3 to NIST 800-53 SC-28, which is why auditors ask for it. It is a configuration finding, not a workload vulnerability; CSPM vs CWPP vs CNAPP explains where each kind of tool fits.
How to confirm it
List attached, unencrypted volumes in a Region with the instance and device each belongs to:
aws ec2 describe-volumes --region us-east-1
--filters Name=encrypted,Values=false Name=attachment.status,Values=attached
--query "Volumes[*].[VolumeId,Attachments[0].InstanceId,Attachments[0].Device,VolumeType,Size]"
--output table
Before touching a volume, record what you need to recreate it: Availability Zone, type, IOPS, throughput, the instance’s root device name and its DeleteOnTermination flags.
aws ec2 describe-volumes --volume-ids vol-0123456789abcdef0
--query "Volumes[].[AvailabilityZone,VolumeType,Size,Iops,Throughput,Encrypted]"
aws ec2 describe-instances --instance-ids i-1234567890abcdef0
--query "Reservations[].Instances[].[RootDeviceName,BlockDeviceMappings[].[DeviceName,Ebs.VolumeId,Ebs.DeleteOnTermination]]"
Check whether encryption by default is already on, and which key it uses:
aws ec2 get-ebs-encryption-by-default --region us-east-1
aws ec2 get-ebs-default-kms-key-id --region us-east-1
To pull the failing volume IDs straight from Security Hub:
aws securityhub get-findings --filters '{
"ComplianceSecurityControlId":[{"Value":"EC2.3","Comparison":"EQUALS"}],
"ComplianceStatus":[{"Value":"FAILED","Comparison":"EQUALS"}],
"RecordState":[{"Value":"ACTIVE","Comparison":"EQUALS"}]}'
--query "Findings[].Resources[].Id"
How to encrypt an existing EBS volume
Before you start
- Pick the key. Without –kms-key-id, EBS uses the Region’s default key (aws/ebs unless changed). Sharing snapshots with other accounts requires a customer managed key, and if Auto Scaling launches volumes with it, its key policy must allow the AWSServiceRoleForAutoScaling role.
- Match the old volume. The CLI creates gp2 unless you pass –volume-type, so copy the type, IOPS and throughput you recorded.
- Stay in the same Availability Zone. A volume attaches only to instances in its own AZ.
Data or root volume: stop, snapshot, swap
This works for data and root volumes. A root volume can only be detached from a stopped instance, and stopping first also gives a consistent snapshot. Substitute your own IDs, Region, AZ, key and device name.
INSTANCE=i-1234567890abcdef0
OLD_VOL=vol-0123456789abcdef0
DEVICE=/dev/xvda # exact name from describe-instances
KEY=alias/my-ebs-key
aws ec2 stop-instances --instance-ids $INSTANCE
aws ec2 wait instance-stopped --instance-ids $INSTANCE
SNAP=$(aws ec2 create-snapshot --volume-id $OLD_VOL
--description "pre-encryption $OLD_VOL" --query SnapshotId --output text)
aws ec2 wait snapshot-completed --snapshot-ids $SNAP
# Optional: also keep an encrypted snapshot (a full copy, billed as one)
ENC_SNAP=$(aws ec2 copy-snapshot --source-region us-east-1
--source-snapshot-id $SNAP --encrypted --kms-key-id $KEY
--query SnapshotId --output text)
aws ec2 wait snapshot-completed --snapshot-ids $ENC_SNAP
NEW_VOL=$(aws ec2 create-volume --availability-zone us-east-1a
--snapshot-id $ENC_SNAP --volume-type gp3 --iops 3000 --throughput 125
--encrypted --kms-key-id $KEY --query VolumeId --output text)
aws ec2 wait volume-available --volume-ids $NEW_VOL
aws ec2 detach-volume --volume-id $OLD_VOL
aws ec2 wait volume-available --volume-ids $OLD_VOL
aws ec2 attach-volume --volume-id $NEW_VOL --instance-id $INSTANCE --device $DEVICE
aws ec2 wait volume-in-use --volume-ids $NEW_VOL
aws ec2 start-instances --instance-ids $INSTANCE
If you skip the copy, pass the unencrypted $SNAP to create-volume; –encrypted is what encrypts the new volume. On large volumes a waiter can give up early, so rerun it. AWS validates the KMS key asynchronously, so a mistyped alias can appear to succeed and fail later: confirm the volume reaches available.
A root volume attached after launch defaults to being preserved at termination. If the original root was set to delete, restore that:
aws ec2 modify-instance-attribute --instance-id $INSTANCE
--block-device-mappings '[{"DeviceName":"/dev/xvda","Ebs":{"DeleteOnTermination":true}}]'
Root volume without a manual stop
The replace root volume task swaps the root volume of a running instance and reboots it automatically. RAM contents are lost, and anything written after your snapshot is not on the new volume. Two options give an encrypted root:
- Enable encryption by default in the Region, then run the task with –snapshot-id and a snapshot taken directly from the current root volume. With encryption by default on, the replacement is always encrypted. Snapshot copies are not accepted.
- Create an encrypted volume from that snapshot yourself (same AZ, state available) and pass it with –volume-id. With this option the original DeleteOnTermination setting does not carry over.
aws ec2 create-replace-root-volume-task
--instance-id i-1234567890abcdef0 --volume-id vol-0fedcba9876543210
aws ec2 describe-replace-root-volume-tasks
--filters Name=instance-id,Values=i-1234567890abcdef0
Leave out –delete-replaced-root-volume so the original stays in your account as a fallback.
AMIs, launch templates and Auto Scaling groups
Fixed instances do not stay fixed if new ones launch from an unencrypted AMI. Create an encrypted copy, point the launch template at it and roll the group:
aws ec2 copy-image --source-image-id ami-0abcdef1234567890
--source-region us-east-1 --region us-east-1
--name "app-base-encrypted" --encrypted --kms-key-id alias/my-ebs-key
A standalone instance can take the same route, but relaunching gives you a new instance ID.
Stop new unencrypted volumes
Encryption by default is per Region, covers only new volumes and snapshot copies, and clears EC2.7. The second command (optional) sets a customer managed default key:
aws ec2 enable-ebs-encryption-by-default --region us-east-1
aws ec2 modify-ebs-default-kms-key-id --kms-key-id alias/my-ebs-key --region us-east-1
Loop over aws ec2 describe-regions to cover every Region you use.
How to verify the fix and rescan
- Rerun the describe-volumes filter in every Region; it should return nothing. The new volume should show Encrypted: true and the expected KmsKeyId.
- On the host, confirm the instance booted and every file system mounted. A volume created from a snapshot starts as an exact replica, so file system UUIDs and labels are unchanged.
- EC2.3 is change triggered: the new volume is evaluated once AWS Config records it, and the detached old volume drops out of scope. Rerun the get-findings query; the old volume ID should no longer appear as an active failure.
What can break and how to roll back
- Slow first reads. Blocks restored from a snapshot are pulled from Amazon S3 on first access, so I/O latency is higher until initialization completes. For busy databases, use a Provisioned Rate for Volume Initialization or fast snapshot restore.
- Wrong device name. Attaching the root on the wrong name, or leaving another root-derived volume attached, can make the instance boot from the wrong volume.
- Silent downgrade. Forgetting –volume-type gives you gp2.
- Key problems. If the KMS key is later disabled or scheduled for deletion, an attached volume keeps working, but the next attach fails until the key is usable again.
- Cost. Encrypting a snapshot copy creates a full, not incremental, copy, and the old volume bills until you delete it.
Rollback is the swap in reverse: stop, detach the new volume, attach the old one on the same device name and start. The replace root volume task cannot go from an encrypted root back to an unencrypted one, so roll back manually. Delete the old volume and unencrypted snapshot after a validation period; until then they still hold unencrypted data.
Common false positive reasons
- Encrypted inside the OS. BitLocker or LUKS protects the data, but EC2.3 reads the EBS Encrypted attribute and still fails. Document it as a compensating control.
- Stale evaluations. AWS Config is not recording EC2 volumes in that Region, so the control never sees your change.
- A key-restricted rule. If someone deployed the encrypted-volumes rule directly in AWS Config with a kmsId parameter, volumes encrypted with any other key fail. The Security Hub control itself takes no parameters.
- The finding keeps coming back. Something launched from an unencrypted AMI in a Region without encryption by default; check the volume ID, it is probably a new one.
- A pass is not the whole picture. Unattached volumes and snapshots are outside EC2.3, so a clean result does not mean every copy of the data is encrypted.
FAQ
Can I encrypt an EBS volume without downtime?
For data volumes, attach a new encrypted volume, copy the data with rsync (Linux) or robocopy (Windows) as AWS documents, then cut the application over. Root volumes need at least a reboot, through either a stop and swap or the replace root volume task.
Does encryption by default fix existing volumes?
No. AWS states it has no effect on existing volumes or snapshots. It only encrypts new volumes and snapshot copies in that Region.
Can I switch back to unencrypted later?
Not on the same volume or snapshot; encryption cannot be removed. Going back means reattaching the old volume.
Should I use aws/ebs or a customer managed key?
aws/ebs is simplest and needs no key policy work. Choose a customer managed key when you share snapshots across accounts or want to create, rotate and disable the key under your own policy.
Tracking this finding across many accounts
At scale, the durable fix is encryption by default in every Region plus encrypted AMIs, with the Security Hub control status as evidence. If you use SITEY, a self-hosted vulnerability management platform that imports findings from 16 scanners, first confirm your cloud posture source is among them. Duplicates are merged per scanner rather than across scanners, and its AI triage suggests false positives with evidence while a human makes the call.