SageMaker notebooks with no lifecycle configuration attached
What does ZopNight detect here?
Lifecycle configurations are the only hook that runs on every notebook start: package installs, security agents, and the auto-stop script that halts idle instances. ZopNight flags in-service notebooks whose lifecycleConfigName is confirmed empty. Severity is low, but the missing auto-stop hook routinely costs more than any 1 misconfiguration here.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1623 |
| Category | compliance |
| Severity | low |
| Metric | none — pure configuration read |
| Source | sagemaker_compliance.go |
Where it applies
The lowest-severity finding with a real invoice attached
Strictly, this is hygiene: a notebook without a lifecycle configuration still works. But the lifecycle config’s on-start hook is where fleets attach the idle auto-stop script, and a notebook without one runs until a human remembers it exists. An ml.m5.xlarge left up over a long weekend bills every one of those hours at its notebook instance rate for zero work. The rule itself claims no dollar figure, since idle detection is a different rule’s job, but the cheapest fix for that whole class of waste is the hook this finding says is missing.
Drift is the other half
Without a lifecycle configuration, every notebook is built by hand: users pip-install their own stacks, clone repos ad hoc, and configure credentials in whatever way occurred to them that morning. Six months later no two instances are alike and none are reproducible. A lifecycle config turns “how notebooks are set up here” from tribal knowledge into a script: version-pinned installs, the security tooling your org requires, and standard repo checkouts, applied identically on every start.
Detection mechanics
Discovery stamps lifecycleConfigName from the notebook description; a present-but-empty
value is the confirmed no-config state and the only one that fires. Absent metadata (failed
describe) abstains, and non-in-service notebooks are excluded so the finding never argues
with a deletion recommendation on the same instance.
See which notebooks lack one
aws sagemaker list-notebook-instances \ --query 'NotebookInstances[].[NotebookInstanceName,NotebookInstanceLifecycleConfigName]' \ --output tableBlank second column, in-service instance: this finding.
Attaching one retroactively
Unlike the VPC and CMK settings, this is repairable in place: stop the notebook, attach the lifecycle configuration, start it. Begin with the auto-stop script (AWS publishes a sample that checks Jupyter idle time and stops the instance), add your provisioning steps, and keep the on-start script fast. A script exceeding the timeout leaves the notebook stuck in Pending, which is how lifecycle configs get a bad name. Once the standard config exists, bake it into the template creating notebooks so new instances never fire this finding at all.