Describe the bug
FoundryCheckpointStore decodes checkpoints without passing allowed_types, so it uses the unrestricted deserialization path. The other two checkpoint stores restrict it.
FileCheckpointStorage and the Cosmos checkpoint storage both take an allowed_checkpoint_types argument, hold it as self._allowed_types, and pass it on:
# packages/core/agent_framework/_workflows/_checkpoint.py
self._allowed_types: frozenset[str] = frozenset(allowed_checkpoint_types or [])
...
decoded_checkpoint_dict = decode_checkpoint_value(encoded_checkpoint, allowed_types=self._allowed_types)
FoundryCheckpointStore has neither, and calls the decoder with the argument omitted, in load and again in list_checkpoints:
# packages/foundry_hosting/agent_framework_foundry_hosting/_state_store.py
return WorkflowCheckpoint.from_dict(decode_checkpoint_value(item.value))
decode_checkpoint_value treats an omitted allowed_types as "no restriction" and falls through to plain pickle.loads, while an empty frozenset — what the other two stores pass by default — selects the restricted unpickler.
The module's own guidance asks for the argument to be supplied:
- The
allowed_types parameter is specified whenever possible to restrict the set of reconstructible types to the minimum required by the application.
Expected behavior
FoundryCheckpointStore restricts deserialization the same way the file and Cosmos stores do, and accepts allowed_checkpoint_types so an application can name the types its checkpoints carry.
Impact on existing applications
This is a behaviour change for applications on the Foundry store whose checkpoints hold their own types and which never registered them, since those applications are currently relying on the store being more permissive than the other two. They would register the types with register_checkpoint_type, or pass allowed_checkpoint_types, which is what an application on the file or Cosmos store already has to do. Aligning the three means a workflow that restores on one store restores on the others.
Platform
- OS: any
- Python version: any
- Package:
agent-framework-foundry-hosting
Describe the bug
FoundryCheckpointStoredecodes checkpoints without passingallowed_types, so it uses the unrestricted deserialization path. The other two checkpoint stores restrict it.FileCheckpointStorageand the Cosmos checkpoint storage both take anallowed_checkpoint_typesargument, hold it asself._allowed_types, and pass it on:FoundryCheckpointStorehas neither, and calls the decoder with the argument omitted, inloadand again inlist_checkpoints:decode_checkpoint_valuetreats an omittedallowed_typesas "no restriction" and falls through to plainpickle.loads, while an emptyfrozenset— what the other two stores pass by default — selects the restricted unpickler.The module's own guidance asks for the argument to be supplied:
Expected behavior
FoundryCheckpointStorerestricts deserialization the same way the file and Cosmos stores do, and acceptsallowed_checkpoint_typesso an application can name the types its checkpoints carry.Impact on existing applications
This is a behaviour change for applications on the Foundry store whose checkpoints hold their own types and which never registered them, since those applications are currently relying on the store being more permissive than the other two. They would register the types with
register_checkpoint_type, or passallowed_checkpoint_types, which is what an application on the file or Cosmos store already has to do. Aligning the three means a workflow that restores on one store restores on the others.Platform
agent-framework-foundry-hosting