Skip to content

fix(security): replace pickle with JSON serialization in ModelRunner shared-memory IPC#860

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-untrusted-input-pickle-use
Draft

fix(security): replace pickle with JSON serialization in ModelRunner shared-memory IPC#860
Copilot wants to merge 2 commits intomainfrom
copilot/fix-untrusted-input-pickle-use

Conversation

Copy link
Contributor

Copilot AI commented Mar 17, 2026

pickle.loads() was used to deserialize data from a POSIX shared memory segment in the tensor-parallel ModelRunner IPC channel. Any process with access to the shared memory segment could inject a malicious payload and achieve arbitrary code execution.

Changes

model_runner.py

  • Drop import pickle; add import json
  • Add _encode_for_shm(items) -> bytes: serializes [method_name, *args] to UTF-8 JSON. Sequence objects are encoded via their existing __getstate__() tuple (ints + lists of ints — all JSON-native). Passing an unsupported type raises TypeError immediately rather than silently pickling it.
  • Add _decode_from_shm(data) -> list: deserializes JSON and reconstructs Sequence via __setstate__() — no pickle.loads path.
  • write_shm / read_shm updated to call the new helpers.
# Before
data = pickle.dumps([method_name, *args])          # write_shm
method_name, *args = pickle.loads(self.shm.buf[4:n+4])  # read_shm

# After
data = _encode_for_shm([method_name, *args])       # write_shm
method_name, *args = _decode_from_shm(bytes(self.shm.buf[4:n+4]))  # read_shm

model_runner_shm_test.py (new)

Eight unit tests covering: prefill/decode-phase Sequence round-trips, multi-sequence batches, primitive type preservation, JSON output validation (asserts the first byte is not the pickle magic 0x80), unsupported-type rejection, and absence of pickle in the module namespace.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Security] pickle used for data deserialization</issue_title>
<issue_description>File: third_parts/nano-vllm/nanovllm/engine/model_runner.py (line 203)

pickle should not be used on untrusted input.</issue_description>

Comments on the Issue (you are @copilot in this section)


📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

…model_runner

Co-authored-by: ChuxiJ <30956809+ChuxiJ@users.noreply.github.com>
Copilot AI changed the title [WIP] [Security] Fix untrusted input pickle usage fix(security): replace pickle with JSON serialization in ModelRunner shared-memory IPC Mar 17, 2026
Copilot AI requested a review from ChuxiJ March 17, 2026 10:02
Copy link
Contributor

@ChuxiJ ChuxiJ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Overall: Solid security improvement. The PR successfully eliminates pickle.loads() from the IPC deserialization path.

Key Items

  1. Medium - Buffer size risk: JSON is typically larger than pickle for the same data. The shared memory buffer is fixed at 1 MB (2**20). For large batches with many sequences containing long token_ids lists, JSON-encoded payloads could exceed this. Consider adding a size check in write_shm to raise a clear error if encoded data exceeds the buffer, rather than silently corrupting memory.

  2. Info - Remaining attack surfaces (pre-existing, out of scope): The hardcoded shared memory name "nanovllm" and getattr(self, method_name) dispatch remain local attack surfaces. Any process on the same machine can write to the shared memory and invoke arbitrary methods on ModelRunner. Not a regression from this PR, but worth tracking separately.

  3. Good practices observed:

    • _enc explicitly raises TypeError on unsupported types (fail-fast)
    • Sequence.__getstate__/__setstate__ round-trip is correctly implemented
    • Thorough test coverage with 8 tests covering round-trips, type preservation, and negative cases
    • json.loads() correctly prevents arbitrary code execution

Style

  • Code follows existing file conventions (module-level underscore-prefixed helpers)
  • Docstrings use Google-style format consistently
  • The test module-level loading pattern is unconventional but justified by torch import avoidance

No blocking issues.

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] pickle used for data deserialization

2 participants