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, the model integrity mechanism offered only a false sense of security, because the 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. AWS holds roughly 28 to 30 percent of the global cloud infrastructure market, so the potential blast radius of this vulnerability covers 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 problem is how the SDK stored and transmitted that key.
The SDK placed the generated key into a container environment variable called SAGEMAKER_SERVE_SECRET_KEY. SageMaker includes container environment variables in API responses, so three describe APIs returned the key in plaintext: 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) ...
In isolation the design sounds reasonable, since HMAC-SHA256 is a solid cryptographic construction. The whole security model collapses once the key itself is stored and transmitted in cleartext. The HMAC gave no more protection than a plain hash, and it also created a false impression of keyed integrity verification.
Attack Flow
The attack runs in five steps, and every one of them requires authenticated access:
-
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. -
The attacker builds a malicious pickle payload that executes arbitrary code when
cloudpickledeserializes it. -
Using the extracted HMAC key, the attacker computes a valid HMAC-SHA256 signature for the malicious artifact.
-
With S3 write access to the model artifact path, the attacker uploads the forged artifact and its matching signature, replacing the legitimate model.
-
When the inference container loads the model, the integrity check passes because the signature is valid, and
cloudpickledeserializes the tampered payload. The attacker gets 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 is the main gate, because the attacker must already have authenticated access to the AWS environment with specific IAM permissions. Once those preconditions are met, exploitation is straightforward and reliable.
Adjacent Vulnerability: CVE-2026-8597
A related vulnerability, CVE-2026-8597, compounds the risk for Triton deployments. The Triton inference handler deserialized model artifacts without performing any integrity verification before execution. On Triton, an attacker only needed S3 write access to the model artifact path to replace artifacts with a malicious pickle payload and achieve code execution, with no need for 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 it 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 is a backport of security fixes originally developed for v3.
The patch modifies 19 files (22 additions, 79 deletions). It removes the secret key entirely and switches from HMAC-SHA256 to plain SHA-256 hashing, which is a surprisingly elegant approach.
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 gone. With a plain cryptographic hash in place of the keyed MAC, there is no secret left to leak. The integrity check now verifies that the artifact has not been corrupted in transit, and it no longer depends on a key that was provably compromisable.
The patch also removes 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 one now calls compute_hash(buffer=buffer) with no key argument.
A particularly important change is in triton/model.py. The Triton model's initialize() method now performs the integrity check before it deserializes 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, because a tampered pickle payload is now rejected before the dangerous deserialization step runs.
In triton/triton_builder.py, the patch removes a hardcoded "dummy secret key for onnx backend" and renames the _hmac_signing() method to _compute_integrity_hash() to reflect the keyless approach.
Remediation Steps
Upgrading the SDK is not enough on its own. Models created with affected SDK versions keep the HMAC key in their container environment variables until they are 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 an immediate upgrade is not feasible, AWS provides two interim workarounds. Remove the SAGEMAKER_SERVE_SECRET_KEY environment variable from existing SageMaker models by recreating the model configuration without it, 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 has a mature vulnerability response process. It published Security Bulletin 2026-031 covering both CVE-2026-8596 and the related CVE-2026-8597, with impacted versions and clear remediation guidance. AWS categorizes its security bulletins as Important or Informational to help customers prioritize patching. The company runs a formal Vulnerability Disclosure Program on HackerOne, alongside direct reporting channels. The timeline here shows 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 before the CVE publication date of May 14, 2026.



