Developer platforms, tools and supply chain
Amazon SageMaker Python SDK: CVE-2026-112408 default bucket takeover
SageMaker Python SDK check
The SDK's default_bucket() uses an S3 bucket named sagemaker-{region}-{AWS account ID}. In affected versions it does not check that the bucket belongs to your account. Region and account ID are not secret, so another AWS account can pre-create a bucket with that name. The SDK then reads from and writes to the attacker's bucket, which can give the attacker code execution in your SageMaker execution environment and your IAM credentials.
| CVE | CVE-2026-112408 (CWE-940, advisory GHSA-5rx8-8fr2-f855, AWS bulletin 2026-142-aws, published 21 October 2026) |
| Severity | Amazon rates it 8.1 (CVSS 3.1); the CNA record also carries 9.4 |
| Affected | V2 before 2.257.3, and V3 (3.0.0) before 3.10.0 |
| Fixed | 2.257.3 and 3.10.0 (both exist on PyPI). The fix adds an ExpectedBucketOwner check to the SDK's S3 operations: comparing the two wheels shows it on the upload, download and bucket-check paths |
| Also | A separate flaw in the same releases (repository credentials written to CloudWatch Logs by git_utils) is fixed by the same upgrade. It is not counted separately here |
Quick start
-
Download the script. The repository is mirrored on GitHub and Codeberg; pick a base URL.
# BASE from GitHub: https://raw.githubusercontent.com/PrivacySafe/security-patches/refs/heads/main # BASE from Codeberg: https://codeberg.org/PrivacySafe/security-patches/raw/branch/main # curl -fLO "$BASE/sagemaker/sagemaker-check.sh" curl -fLO https://raw.githubusercontent.com/PrivacySafe/security-patches/refs/heads/main/sagemaker/sagemaker-check.sh -
Read it before running it, then make it executable.
less sagemaker-check.sh chmod +x sagemaker-check.sh -
Check this host. By default it searches
/usr/lib /usr/local/lib /opt /srv /var/lib /home /root. Pass directories to narrow it, such as one virtual environment../sagemaker-check.sh check ./sagemaker-check.sh check ~/ml/.venv
Commands
| Command | What it does |
|---|---|
check [DIR ...] (default) |
Finds installed copies (sagemaker-*.dist-info and egg-info) and declared pins (requirements*.txt, poetry.lock, uv.lock, pdm.lock, Pipfile.lock, environment*.yml), and lists the Python files and notebooks that call default_bucket(). It makes no AWS calls |
version |
Prints the script version |
Exit codes: 0 nothing affected, 1 an affected SDK found, 2 bad arguments.
How to read the result
-
Affected version: exit
1. The tool cannot prove your code relies on the default bucket (estimators and processors use it implicitly), so it judges by version and lists the files that calldefault_bucket()directly, excluding the SDK's own source. -
The SDK's own packages and look-alikes such as
sagemaker-coreandsagemaker_studioare different packages and are not matched, including when listed before the real one in a lock file. -
It cannot tell whether someone has already pre-created your bucket name. To check by hand, with the AWS CLI and read access (this script does not run it):
aws s3api head-bucket --bucket sagemaker-REGION-ACCOUNTID --expected-bucket-owner ACCOUNTIDA 404 suggests the name is unclaimed and anyone could take it. A 403 usually means it exists under a different account (or that you lack permission). If it is someone else's, review what the SDK uploaded there.
Fixing it
pip install --upgrade 'sagemaker>=2.257.3' # V2
pip install --upgrade 'sagemaker>=3.10.0' # V3
Until you can upgrade (PrivacySafe recommendation): pass an explicit bucket you own instead of relying on the default (V2's Session documents a default_bucket argument; use the equivalent setting in V3), and create the default bucket sagemaker-<region>-<account-id> yourself so no one else can.
Sources
Before you run it
- The fix. Update the SageMaker Python SDK to 2.257.3 (V2) or 3.10.0 (V3). The same upgrade fixes a separate flaw that wrote repository credentials to CloudWatch Logs.
- It makes no AWS calls. It finds installed copies and pinned versions, and lists the Python files and notebooks that call
default_bucket(). - It cannot tell whether someone has pre-created your bucket name. That is the real exposure, so the script prints a manual check for you to run.
- There is no hunt. No indicators of exploitation have been published.
- It also checks running docker and podman containers, unless you name a directory or set
SCAN_CONTAINERS=0. In each running container, a read-only probe copies the SageMaker SDK metadata folders and the lock, requirements andenvironment*.ymlfiles that mention it into a private temporary folder, with index URLs and credentials dropped inside the container. The script then runs once per container, in isolation, against that copy. A path shown as.../docker_NAME/PATHis the PATH inside the container NAME.
The Security Patches software and this documentation are dedicated to the public domain under CC0 1.0 Universal. Other pages on privacysafe.app/docs are CC BY-SA 4.0 unless the page says otherwise.