Python: Harden FoundryCheckpointStore: apply RestrictedUnpickler allowlist on checkpoint load - #7820
Closed
herdiyanitdev (herdiyana256) wants to merge 1 commit into
Conversation
herdiyanitdev (herdiyana256)
temporarily deployed
to
github-app-auth
August 22, 2026 15:15 — with
GitHub Actions
Inactive
herdiyanitdev (herdiyana256)
temporarily deployed
to
github-app-auth
August 22, 2026 15:15 — with
GitHub Actions
Inactive
herdiyanitdev (herdiyana256)
had a problem deploying
to
github-app-auth
August 22, 2026 15:15 — with
GitHub Actions
Error
herdiyanitdev (herdiyana256)
temporarily deployed
to
github-app-auth
August 22, 2026 15:15 — with
GitHub Actions
Inactive
Copilot started reviewing on behalf of
herdiyanitdev (herdiyana256)
August 22, 2026 15:15
View session
… load FoundryCheckpointStore was the only checkpoint backend calling decode_checkpoint_value(item.value) without allowed_types, falling back to unrestricted pickle.loads. FileCheckpointStorage and CosmosCheckpointStorage both thread the RestrictedUnpickler allowlist through. Thread allowed_checkpoint_types through FoundryCheckpointStore and CheckpointStoreProvider, and pass allowed_types on both load() and list_checkpoints(). Default (frozenset()) restricts deserialization to the built-in safe set plus framework and OpenAI SDK types, matching the other backends. Legitimate checkpoints round-trip unchanged.
Contributor
There was a problem hiding this comment.
Pull request overview
Hardens hosted checkpoint deserialization by applying the framework’s restricted unpickler allowlist.
Changes:
- Adds configurable checkpoint type allowlisting.
- Applies restrictions to checkpoint loading and listing.
- Adds security and provider-forwarding tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
_state_store.py |
Enforces and propagates deserialization allowlists. |
test_state_store.py |
Tests restricted defaults and provider propagation. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+171
to
175
| checkpoint = WorkflowCheckpoint.from_dict( | ||
| decode_checkpoint_value(item.value, allowed_types=self._allowed_types) | ||
| ) | ||
| if checkpoint.workflow_name == workflow_name: | ||
| checkpoints.append(checkpoint) |
herdiyanitdev (herdiyana256)
force-pushed
the
fix/foundry-checkpoint-restricted-unpickler
branch
from
August 22, 2026 15:17
cc1b41f to
91843c6
Compare
herdiyanitdev (herdiyana256)
temporarily deployed
to
github-app-auth
August 22, 2026 15:17 — with
GitHub Actions
Inactive
Author
|
Closing; will resubmit later. |
herdiyanitdev (herdiyana256)
deleted the
fix/foundry-checkpoint-restricted-unpickler
branch
August 22, 2026 15:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Harden FoundryCheckpointStore: apply RestrictedUnpickler allowlist on checkpoint load
Summary
FoundryCheckpointStore(foundry_hosting) is the only checkpoint backend thatcalls
decode_checkpoint_value(item.value)withoutallowed_types, so it fallsback to unrestricted
pickle.loads. Every other backend threads the allowlistthrough:
FileCheckpointStorage(_workflows/_checkpoint.py)decode_checkpoint_value(..., allowed_types=self._allowed_types)CosmosCheckpointStorage(azure-cosmos/_checkpoint_storage.py)decode_checkpoint_value(cleaned, allowed_types=self._allowed_types)FoundryCheckpointStore(foundry_hosting/_state_store.py)decode_checkpoint_value(item.value)— no allowlistThis PR aligns
FoundryCheckpointStorewith the framework's own security model:the
RestrictedUnpicklerallowlist (the documented defense-in-depth control) is nowapplied on every hosted checkpoint load, restricted-by-default, with an optional
allowed_checkpoint_typesescape hatch identical to the other backends.Rationale
foundry_hosting is the multi-tenant, network-facing hosting path. It is inconsistent
for the one hosted backend to silently drop the allowlist that
FileCheckpointStorageand
CosmosCheckpointStorageboth enforce. This is a defense-in-depth hardening thatrestores parity; it is not a claim that checkpoint storage is a security boundary
(the docs correctly state it is a trusted data source).
Changes
FoundryCheckpointStore.__init__acceptsallowed_checkpoint_types: list[str] | Noneand stores
self._allowed_types = frozenset(allowed_checkpoint_types or [])(same shape as
FileCheckpointStorage).load()andlist_checkpoints()passallowed_types=self._allowed_typestodecode_checkpoint_value. Default (frozenset()) → restricted unpickler(built-in safe types +
agent_framework.*+openai.types.*).CheckpointStoreProvider.__init__acceptsallowed_checkpoint_typesand threads itinto every store it creates.
Backward compatibility
Legitimate checkpoints produced by
encode_checkpoint_valuecontain only primitives,collections, framework types, and OpenAI SDK types — all covered by the built-in safe
set — so they continue to round-trip under the restricted default (verified). Apps
persisting custom state types widen the allowlist via
allowed_checkpoint_types,exactly as with the file/cosmos backends.
Tests
test_load_defaults_to_restricted_unpickler_and_blocks_unlisted_types— a plantedpickle envelope resolving to
os.systemis rejected (WorkflowCheckpointException)instead of executing.
test_checkpoint_store_provider_threads_allowed_types— provider forwards theallowlist to created stores.
test_checkpoint_store_defaults_to_empty_allowlist— default is restricted(
frozenset()), notNone(unrestricted).