Skip to content

security: restrict pickle deserialization in v0 schema and migration tool#5635

Open
daridor9 wants to merge 5 commits intogoogle:mainfrom
daridor9:fix/restricted-unpickler-v0
Open

security: restrict pickle deserialization in v0 schema and migration tool#5635
daridor9 wants to merge 5 commits intogoogle:mainfrom
daridor9:fix/restricted-unpickler-v0

Conversation

@daridor9
Copy link
Copy Markdown

@daridor9 daridor9 commented May 7, 2026

Summary

This PR adds a RestrictedUnpickler to prevent arbitrary code execution via crafted pickle payloads in the v0 schema runtime path and the migration tool.

Fixes #5634

Changes

New: _safe_unpickle.py

  • RestrictedUnpickler subclass that allowlists only known-safe types:
    • ADK model types (google.adk.*)
    • Google GenAI types (google.genai.*)
    • Pydantic internals (pydantic.*, pydantic_core.*)
    • Standard Python builtins and collections/datetime/copyreg
  • Blocks all other globals (e.g., os, subprocess, posix, builtins.__import__)
  • safe_loads() function as drop-in replacement for pickle.loads()
  • Escape hatch: ADK_ALLOW_UNSAFE_V0_PICKLE=1 env var for databases with non-standard pickled types (logs deprecation warning)

Patched: v0.py (Sink 1 — runtime read path)

  • DynamicPickleType.process_result_value() now calls safe_loads() instead of pickle.loads()
  • Affects MySQL, Cloud Spanner, and SQLite dialects

Patched: migrate_from_sqlalchemy_pickle.py (Sink 2 — migration path)

  • _row_to_event() now calls safe_loads() instead of pickle.loads()
  • Ensures adk migrate session is safe to run on untrusted v0 databases

Testing

  • Existing v0 databases with legitimate EventActions pickle data will continue to work — all ADK types are allowlisted
  • Malicious pickle payloads (e.g., os.system, subprocess.Popen) are blocked with a clear error message
  • The env var escape hatch provides a migration path for edge cases

Security Context

  • Reported to Google VRP: 2026-04-24
  • GHSA filed
  • CVSS 3.1: 9.9 Critical (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H)
  • 90-day coordinated disclosure deadline: 2026-07-23

Submitted by SPR{K}3 Security Research (@daridor9)

daridor9 added 3 commits May 7, 2026 21:17
Replace raw pickle.loads() with safe_loads() in
DynamicPickleType.process_result_value().

Ref: google#5634
Replace raw pickle.loads() with safe_loads() in
_row_to_event() migration function.

Ref: google#5634
@google-cla
Copy link
Copy Markdown

google-cla Bot commented May 7, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@adk-bot
Copy link
Copy Markdown
Collaborator

adk-bot commented May 7, 2026

Hello @daridor9, thank you for your contribution! This is a valuable security fix.

Before we can proceed with the review, could you please sign the Contributor License Agreement (CLA)? The cla/google check is currently failing. You can find details on how to sign it in our contribution guidelines.

Once the CLA is signed, we can move forward with labeling and reviewing your PR.

Response from ADK Triaging Agent

Covers potential enum values in state_delta/agent_state dict[str, Any] fields.

Ref: google#5634
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security: Unsafe pickle.loads() in v0 schema runtime path and migration tool

2 participants