Skip to content

Fix RCE: refuse object-dtype arrays in msgpack deserialization - #49

Merged
nicholas9182 merged 6 commits into
devfrom
fix/serializer-pickle-rce
Sep 29, 2026
Merged

nicholas9182 merged 6 commits into
devfrom
fix/serializer-pickle-rce

Conversation

@0x1r1s

@0x1r1s 0x1r1s commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator

msgpack_numpy.decode calls pickle.loads on object-dtype ('O') numpy arrays. m.patch() makes it the global msgpack object_hook, so any msgpack.unpackb in the process runs pickle.loads on such an array. pickle.loads runs arbitrary code, so an untrusted payload (for example an uploaded .ocd design) could execute code during unpack, before any class allowlist check. The patched reader also wraps a caller-supplied object_hook and runs decode first, so a hook cannot make unpack safe.

Capture the unpatched msgpack.unpackb before m.patch(), then re-override msgpack.unpackb/loads with a safe reader that refuses object-dtype arrays and delegates all other maps (numeric/void arrays, complex numbers, plain dicts) to the normal decoder. Writing (packb) is unchanged. No cell design uses object-dtype arrays (verified against the OpenCell database: 45895 arrays, all numeric, zero object arrays), so the refusal breaks no real design.

0x1r1s and others added 6 commits September 29, 2026 11:01
msgpack_numpy.decode calls pickle.loads on object-dtype ('O') numpy
arrays. m.patch() makes it the global msgpack object_hook, so any
msgpack.unpackb in the process runs pickle.loads on such an array.
pickle.loads runs arbitrary code, so an untrusted payload (for example
an uploaded .ocd design) could execute code during unpack, before any
class allowlist check. The patched reader also wraps a caller-supplied
object_hook and runs decode first, so a hook cannot make unpack safe.

Capture the unpatched msgpack.unpackb before m.patch(), then re-override
msgpack.unpackb/loads with a safe reader that refuses object-dtype
arrays and delegates all other maps (numeric/void arrays, complex
numbers, plain dicts) to the normal decoder. Writing (packb) is
unchanged. No cell design uses object-dtype arrays (verified against the
OpenCell database: 45895 arrays, all numeric, zero object arrays), so
the refusal breaks no real design.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
0.2.24 is already on PyPI and is now used by PR #48.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nicholas9182
nicholas9182 merged commit 3c311ac into dev Sep 29, 2026
1 check passed
@0x1r1s
0x1r1s deleted the fix/serializer-pickle-rce branch September 30, 2026 16:52
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.

2 participants