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.