This check flags SageMaker notebook instances created without a KMS key, which means the attached ML storage volume is encrypted only with a default AWS-managed key you cannot audit or rotate on your terms. Recreate the notebook with a customer managed KMS key to get auditable, controllable encryption at rest.
SageMaker notebook instances are convenient, managed Jupyter environments where data scientists pull in training data, experiment with models, and stash credentials in environment variables more often than anyone wants to admit. The storage volume attached to that notebook holds all of it: datasets, intermediate artifacts, cached secrets, and the notebooks themselves. If that volume is not encrypted with a key you control, you lose a meaningful layer of defense and you usually lose a compliance check too.
This Lensix check, sagemaker_unencrypted, looks at each SageMaker notebook instance in your AWS account and verifies that a KMS key ID is set on the instance. When the field is empty, the notebook either has no explicit key or falls back to default AWS-managed encryption, and the check fails.
What this check detects
When you create a SageMaker notebook instance, you can optionally specify a KmsKeyId. That key encrypts the ML storage volume (an EBS volume) attached to the instance. The check inspects the notebook configuration and fails when no customer managed KMS key is associated.
You can confirm the current state of any notebook with the AWS CLI:
aws sagemaker describe-notebook-instance \
--notebook-instance-name my-notebook \
--query '{Name:NotebookInstanceName, KmsKeyId:KmsKeyId, Status:NotebookInstanceStatus}'
If KmsKeyId comes back as null or is missing from the output, the notebook has no customer managed key and this check will fail.
Note: A null KmsKeyId does not mean the volume is plaintext on disk. AWS still encrypts the underlying storage with an AWS-managed key. The problem is that you have no visibility into that key, no control over its policy, and no ability to rotate or revoke it independently. For most audit and compliance frameworks, that is treated the same as unencrypted.
Why it matters
The risk here is less about a single dramatic breach and more about losing control over your encryption boundary. A few concrete scenarios make this tangible.
You cannot enforce key access separately from notebook access
With a customer managed key, you decide who can use that key through the KMS key policy and IAM. If an attacker or an over-privileged role gains access to the EBS volume or a snapshot of it, decryption still requires permission to use your KMS key. With the default AWS-managed key, that separate control point does not exist. Anyone with the right SageMaker and EC2 permissions can read the data.
Snapshots and volume cloning leak data
The ML storage volume can be snapshotted. If those snapshots are created from a volume encrypted with a customer managed key, the snapshot inherits that key and stays protected. Without a key you control, a copied snapshot is only as protected as the default key, which you cannot scope down.
Compliance findings pile up
PCI DSS, HIPAA, SOC 2, and FedRAMP auditors generally expect customer managed encryption keys for data stores that hold sensitive information. SageMaker notebooks routinely hold PII, PHI, and proprietary model data. A notebook without a CMK is a recurring finding that shows up in every audit cycle until you fix it.
Warning: Data scientists frequently hardcode database credentials, API tokens, and access keys inside notebook cells or shell history during experimentation. That makes the storage volume a high-value target, not a throwaway scratch disk. Treat notebook encryption with the same seriousness as a production database.
How to fix it
Here is the catch that trips most people up: you cannot add or change the KMS key on an existing SageMaker notebook instance. The KmsKeyId is set at creation and is immutable. Fixing this means recreating the notebook with a key attached.
Step 1: Create or pick a KMS key
If you do not already have a key earmarked for SageMaker, create one:
aws kms create-key \
--description "SageMaker notebook encryption" \
--tags TagKey=Purpose,TagValue=sagemaker
# Optionally give it a friendly alias
aws kms create-alias \
--alias-name alias/sagemaker-notebooks \
--target-key-id <key-id-from-previous-output>
Step 2: Back up anything you need from the old notebook
Danger: Deleting a notebook instance destroys its ML storage volume and everything on it that was not committed to a repo or copied to S3. Before you delete, push your notebooks to Git or sync the working directory to S3. There is no undo.
# From inside the notebook terminal, sync your work to S3
aws s3 sync /home/ec2-user/SageMaker/ s3://my-backup-bucket/notebook-backup/
Step 3: Stop and delete the unencrypted notebook
aws sagemaker stop-notebook-instance \
--notebook-instance-name my-notebook
# Wait for status to reach 'Stopped', then delete
aws sagemaker delete-notebook-instance \
--notebook-instance-name my-notebook
Step 4: Recreate the notebook with the KMS key
aws sagemaker create-notebook-instance \
--notebook-instance-name my-notebook \
--instance-type ml.t3.medium \
--role-arn arn:aws:iam::123456789012:role/SageMakerExecutionRole \
--kms-key-id alias/sagemaker-notebooks \
--subnet-id subnet-0abc123 \
--security-group-ids sg-0def456
Once the instance reaches InService, restore your work from S3 and confirm the key is attached with the describe-notebook-instance command from earlier.
Doing it with infrastructure as code
If you manage notebooks in Terraform, set kms_key_id on the resource so it is correct from the first apply:
resource "aws_kms_key" "sagemaker" {
description = "SageMaker notebook encryption"
enable_key_rotation = true
}
resource "aws_sagemaker_notebook_instance" "this" {
name = "my-notebook"
role_arn = aws_iam_role.sagemaker.arn
instance_type = "ml.t3.medium"
kms_key_id = aws_kms_key.sagemaker.arn
subnet_id = var.subnet_id
security_groups = [var.security_group_id]
direct_internet_access = "Disabled"
}
Tip: Enable automatic key rotation on the KMS key (enable_key_rotation = true in Terraform, or aws kms enable-key-rotation in the CLI). AWS rotates the backing material yearly with no impact on existing data, and it knocks out a separate set of compliance findings about key rotation at the same time.
How to prevent it from happening again
Because the key cannot be changed after creation, prevention matters far more here than remediation. You want to catch a missing key before the notebook ever exists.
Block it in Terraform with a policy check
If you use Terraform, a policy-as-code tool like OPA or Checkov can fail the plan when kms_key_id is absent. A simple Checkov custom check or the built-in CKV_AWS_22 rule covers SageMaker encryption. Run it in CI:
checkov -d . --check CKV_AWS_22
Add an OPA Conftest rule
package main
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_sagemaker_notebook_instance"
not resource.change.after.kms_key_id
msg := sprintf("SageMaker notebook '%s' must set kms_key_id", [resource.address])
}
Detect drift continuously
IaC gates only cover resources created through your pipeline. Anyone with console access can still spin up a notebook by hand without a key. A continuous scanning tool like Lensix closes that gap by checking every notebook in the account on a schedule, including the ones nobody told you about, and alerting on any that lack a customer managed key.
Note: AWS Config has a managed rule, sagemaker-notebook-instance-kms-key-configured, that flags notebooks without a KMS key. It is a reasonable native backstop if you are not already running a dedicated posture management tool.
Best practices
- Always set a customer managed KMS key at creation. Make it a non-negotiable field in your notebook templates and modules so nobody has to remember it.
- Scope the KMS key policy tightly. Grant
kms:Decryptandkms:GenerateDataKeyonly to the SageMaker execution role and the specific principals who genuinely need it. - Disable direct internet access on notebooks (
direct_internet_access = "Disabled") and run them inside a VPC. Encryption protects data at rest, but network isolation protects it in use. - Keep secrets out of notebooks. Pull credentials from AWS Secrets Manager or Parameter Store at runtime instead of pasting them into cells. Encryption does not help if the secret is also sitting in a Git history.
- Stop idle notebooks automatically. A lifecycle configuration that stops instances after inactivity reduces both cost and the window during which data sits on a running volume.
- Use one key strategy per environment. Separate keys for dev, staging, and production make it easy to revoke access to a single environment without affecting the others.
The short version: set the key when you build the notebook, gate it in CI, and scan continuously for the ones that slip through. Because the key is immutable, every notebook you fix after the fact costs you a recreate. Catch it up front and you never pay that tax.

