pickle

package
v0.783.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 29, 2026 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Overview

Package pickle disassembles a Python pickle byte stream into its opcode sequence and flags the code-execution opcodes that make a pickle dangerous — without ever unpickling it.

Python pickle is a stack-machine bytecode (PEP 307 / CPython Lib/pickle.py), and a malicious pickle is a top supply-chain RCE vector: PyTorch / TensorFlow / scikit-learn / HuggingFace model files, joblib caches, and Redis values are all pickles, and merely *loading* one with pickle.load runs whatever the GLOBAL + REDUCE opcodes encode (the classic gadget is GLOBAL os system / STACK_GLOBAL + REDUCE). This walks the opcode stream — the safe operation that pickletools.dis performs, never pickle.load — and reports the protocol version, every opcode, the imported callables (module.name from GLOBAL / STACK_GLOBAL / INST), and whether the pickle can execute code (an import opcode plus an invocation opcode), with the known-dangerous imports (os / subprocess / builtins.eval / …) called out.

No confidently-wrong output: the opcode and argument encodings are transcribed verbatim from CPython's pickletools.opcodes; an unknown opcode stops the walk (the argument length is then unknown) and is reported as such rather than guessed; every length field is bounds-checked against the remaining input; and the stream is never executed. STACK_GLOBAL's target is resolved heuristically from the two preceding string pushes (how the pickler emits it) and labelled as such.

Wrap-vs-native: native — a byte-cursor walk of the documented opcode set; stdlib only, no new go.mod dependency. Verified opcode-for-opcode against Python's stdlib pickletools (see the package test).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Op

type Op struct {
	Pos    int    `json:"pos"`
	Opcode string `json:"opcode"`
	Arg    string `json:"arg,omitempty"`
}

Op is one disassembled opcode.

type Result

type Result struct {
	Format   string `json:"format"`
	Protocol int    `json:"protocol"`
	Opcodes  []Op   `json:"opcodes"`
	OpCount  int    `json:"opcode_count"`
	// Imports are the module.name callables referenced by GLOBAL / STACK_GLOBAL /
	// INST (STACK_GLOBAL resolved heuristically — see DangerousImports note).
	Imports []string `json:"imports,omitempty"`
	// DangerousImports is the subset of Imports matching a known RCE sink.
	DangerousImports []string `json:"dangerous_imports,omitempty"`
	// CodeExecOpcodes are the invocation opcodes present (REDUCE / OBJ / NEWOBJ /
	// NEWOBJ_EX / INST / BUILD) — a pickle carrying these runs code on load.
	CodeExecOpcodes []string `json:"code_exec_opcodes,omitempty"`
	// ExecutesCode is true when both an import and an invocation opcode are present.
	ExecutesCode bool `json:"executes_code"`
	// Truncated is true when the walk stopped before STOP (unknown opcode or a
	// short/over-long argument).
	Truncated bool   `json:"truncated,omitempty"`
	Note      string `json:"note"`
}

Result is the disassembled pickle.

func Decode

func Decode(data []byte) (*Result, error)

Decode disassembles a pickle byte stream.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL