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

  1. 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
    
  2. Read it before running it, then make it executable.

    less sagemaker-check.sh
    chmod +x sagemaker-check.sh
    
  3. 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 call default_bucket() directly, excluding the SDK's own source.

  • The SDK's own packages and look-alikes such as sagemaker-core and sagemaker_studio are 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 ACCOUNTID
    

    A 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 and environment*.yml files 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/PATH is 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.

Edit this page on Codeberg

The PrivacySafe Ecosystem

Shop at Ivy Cyber

Ivy Cyber offers PrivacySafe products and services in the USA and has partnerships with 3NSoft in Canada and Kuip Limited in the European Union. Enterprise services and consulting are available at ivycyber.com

PrivacySafe Foundation is a 501(c)(3) nonprofit public charity that supports the development of the PrivacySafe applications, along with the components they rely upon: 3NWeb protocols, filesystem, documentation, and reference implementations.

PrivacySafe Foundation

Donations to PrivacySafe Foundation support education, research, documentation, and public code. Purchases from Ivy Cyber support PrivacySafe products, services, hosting, and technical support. Together, we're building a better web.