Introduction
A cleartext key storage flaw in the Amazon SageMaker Python SDK allowed authenticated attackers to extract an HMAC signing secret from standard API responses, forge valid integrity signatures for malicious model artifacts, and achieve arbitrary code execution inside inference containers. For organizations running ML inference workloads on SageMaker, this vulnerability quietly turned a model integrity mechanism into a false sense of security, since the very key protecting artifact integrity was readable by anyone with describe API permissions.
Amazon SageMaker is a widely adopted managed service and open source library for training and deploying machine learning models at scale. Its ModelBuilder component automates artifact preparation and deployment across multiple inference server frameworks. Given that AWS holds roughly 28 to 30 percent of the global cloud infrastructure market, the potential blast radius of this vulnerability spans a significant portion of enterprise AI operations.
Technical Information
Root Cause: Cleartext HMAC Key in Container Environment Variables
The vulnerability is classified under CWE-312 (Cleartext Storage of Sensitive Information). When deploying models via the ModelBuilder/Serve component, the SDK generates an HMAC-SHA256 secret key to verify the integrity of serialized model artifacts. The fundamental problem is how this key was stored and transmitted.
The SDK placed the generated key into a container environment variable called SAGEMAKER_SERVE_SECRET_KEY. Because SageMaker includes container environment variables in API responses, the key was returned in plaintext by three describe APIs: DescribeModel, DescribeEndpointConfig, and DescribeModelPackage.
The vulnerable code in src/sagemaker/serve/validations/check_integrity.py looked like this:
# BEFORE (vulnerable) def generate_secret_key(nbytes: int = 32) -> str: return secrets.token_hex(nbytes) def compute_hash(buffer: bytes, secret_key: str) -> str: return hmac.new(secret_key.encode(), msg=buffer, digestmod=hashlib.sha256).hexdigest() def perform_integrity_check(buffer: bytes, metadata_path: Path): secret_key = os.environ.get("SAGEMAKER_SERVE_SECRET_KEY") actual_hash_value = compute_hash(buffer=buffer, secret_key=secret_key) ...
The design sounds reasonable in isolation: HMAC-SHA256 is a solid cryptographic construction. But the entire security model collapses when the key itself is stored and transmitted in cleartext. The HMAC provided no more protection than a plain hash, and worse, it created a false impression of keyed integrity verification.
Attack Flow
Exploitation proceeds through a clear sequence of steps, all requiring authenticated access:
-
Key Extraction: An attacker with IAM permissions to call SageMaker describe APIs queries
DescribeModel,DescribeEndpointConfig, orDescribeModelPackage. The response includes theSAGEMAKER_SERVE_SECRET_KEYenvironment variable value in plaintext. -
Payload Construction: The attacker crafts a malicious pickle payload designed to execute arbitrary code upon deserialization by
cloudpickle. -
Signature Forgery: Using the extracted HMAC key, the attacker computes a valid HMAC-SHA256 signature for the malicious artifact.
-
Artifact Replacement: With S3 write access to the model artifact path, the attacker uploads the forged artifact and its matching signature, replacing the legitimate model.
-
Code Execution: When the inference container loads the model, the integrity check passes (the signature is valid), and
cloudpickledeserializes the tampered payload. The attacker achieves arbitrary code execution with the IAM permissions of the SageMaker execution role.
Affected Model Servers
The SAGEMAKER_SERVE_SECRET_KEY environment variable was propagated across all supported model server variants:
| Model Server | Affected Files |
|---|---|
| TorchServe | torchserve/server.py, torchserve/prepare.py |
| Multi Model Server (MMS) | multi_model_server/server.py, multi_model_server/prepare.py |
| TensorFlow Serving | tensorflow_serving/server.py, tensorflow_serving/prepare.py |
| SageMaker Distributed (SMD) | smd/server.py, smd/prepare.py |
| Triton | triton/server.py, triton/model.py |
| TEI | tei/server.py |
CVSS Metrics and Preconditions
The CVSS 4.0 base score is 8.5 (High) and the CVSS 3.1 score is 7.2 (High). The Attack Vector is Network, Attack Complexity is Low, Privileges Required is High, and User Interaction is None. The High privilege requirement acts as a gating factor: the attacker must already possess authenticated access to the AWS environment with specific IAM permissions. However, once those preconditions are met, exploitation is straightforward and reliable.
Adjacent Vulnerability: CVE-2026-8597
A related vulnerability, CVE-2026-8597, compounds the risk specifically for Triton deployments. The Triton inference handler deserialized model artifacts without performing any integrity verification at all before execution. For Triton deployments, an attacker only needed S3 write access to the model artifact path to replace artifacts with a malicious pickle payload, achieving code execution without needing access to the describe APIs or the HMAC key. Organizations should treat these two vulnerabilities as a combined threat vector.
Patch Information
AWS published the fix in PR #5656, merged on April 1, 2026 (commit 48f45dab), and shipped in two release branches: v2.257.2 (April 21, 2026) and v3.8.0 (April 16, 2026). The commit is titled "fix: Security fixes for Triton HMAC key exposure and missing integrity check (v2)" and constitutes a backport of security fixes originally developed for v3.
The patch spans 19 modified files (22 additions, 79 deletions) and takes a surprisingly elegant approach: it removes the secret key entirely and switches from HMAC-SHA256 to plain SHA-256 hashing.
The core change in src/sagemaker/serve/validations/check_integrity.py:
# AFTER (patched) def compute_hash(buffer: bytes) -> str: return hashlib.sha256(buffer).hexdigest() def perform_integrity_check(buffer: bytes, metadata_path: Path): actual_hash_value = compute_hash(buffer=buffer) ...
The generate_secret_key() function and the os.environ.get("SAGEMAKER_SERVE_SECRET_KEY") dependency are removed entirely. By eliminating the keyed MAC in favor of a plain cryptographic hash, there is simply no secret to leak. The integrity check now verifies that the artifact has not been corrupted in transit, but no longer depends on a key that was provably compromisable.
Beyond the core hashing change, the patch systematically scrubs the SAGEMAKER_SERVE_SECRET_KEY environment variable from every model server variant listed above. All prepare.py files previously called generate_secret_key() and passed the key through compute_hash(buffer=buffer, secret_key=secret_key). Each was updated to simply call compute_hash(buffer=buffer) with no key argument.
A particularly important part of the fix is in triton/model.py, where the Triton model's initialize() method now performs the integrity check before deserializing with cloudpickle. The old code had a TODO: HMAC signing for integrity check comment and performed no verification at all before calling cloudpickle.load(f). The patched version reads the raw bytes, calls perform_integrity_check(), and only then calls cloudpickle.loads(buffer). This ordering is security critical: it ensures a tampered pickle payload is rejected before the dangerous deserialization step runs.
Additionally, in triton/triton_builder.py, a hardcoded "dummy secret key for onnx backend" was removed, and the _hmac_signing() method was renamed to _compute_integrity_hash() to reflect the new keyless approach.
Remediation Steps
Upgrading the SDK alone is insufficient. Models created with affected SDK versions will continue to store the HMAC key in their container environment variables until explicitly rebuilt. The required remediation is:
- Upgrade the Amazon SageMaker Python SDK to v2.257.2 or v3.8.0.
- Rebuild any models previously created with ModelBuilder using the updated SDK.
For environments where immediate upgrades are not feasible, AWS provides interim workarounds: manually remove the SAGEMAKER_SERVE_SECRET_KEY environment variable from existing SageMaker models by recreating the model configuration without that variable, and restrict S3 write access for model artifact paths to trusted principals only.
Affected Systems and Versions
| SDK Track | Affected Versions | Fixed Version |
|---|---|---|
| Version 2 | 2.199.0 through 2.257.1 | 2.257.2 |
| Version 3 | 3.0.0 through 3.7.1 | 3.8.0 |
The vulnerability specifically affects deployments that use the ModelBuilder component to build and deploy models. Affected model server frameworks include TorchServe, Multi Model Server, TensorFlow Serving, SageMaker Distributed (SMD), Triton, and TEI.
Exploitation requires an authenticated actor with:
- IAM permissions to call
DescribeModel,DescribeEndpointConfig, orDescribeModelPackageAPIs - S3 write access to the model artifact path
Vendor Security History
AWS demonstrates a mature vulnerability response process. The vendor published Security Bulletin 2026-031 detailing both CVE-2026-8596 and the related CVE-2026-8597, including impacted versions and clear remediation guidance. AWS publishes security bulletins categorized as Important or Informational to help customers prioritize patching. The company operates a formal Vulnerability Disclosure Program hosted on HackerOne, alongside direct reporting channels. The timeline here reflects proactive patch management: the fix was merged on April 1, 2026, shipped in v3.8.0 on April 16, 2026, and in v2.257.2 on April 21, 2026, all prior to the CVE publication date of May 14, 2026.



