dill 0.4.1
- Source
- https://github.com/uqfoundation/dill
- Tag scanned
0.4.1- Compared with
0.4.0(0 signals introduced since)- Files
- 56 scanned, 9 skipped (binary, oversized, or unrecognised)
- Signals
- 1 critical · 2 warn · 46 info
- Scan time
- 39.4 s
- LLM review
- Reviewed by claude-haiku-5-5 (Anthropic): 49 of 49 warn and critical signals; 46 demoted to info.
- Disclude version
- 4.0.0
- Scanned (UTC)
- 2026-10-14 18:49
Signals
Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.
-
try: res = os.system(msg) except Exception: print ("Please verify install of 'gprof2dot' to view profile graphs")likely benign Profiling script shells out to gprof2dot and dot to render a profile graph.Reasoning
os.system runs a command string built at runtime, which is a shell-injection risk if file names are untrusted. The surrounding code is a legitimate gprof2dot/dot pipeline with a helpful error message, so it looks like a robustness issue rather than a dropper or malicious payload.
-
for line in obj[:-1]: exec(line) # one-line generation of an instance try:likely benign Developer profiling script execs reconstructed instance-generation lines from its own data.Reasoning
The exec runs lines from a developer-facing profiling script that rebuilds object instances from its own generated output. Executing data from a file is a code-quality and trust concern if the input is untrusted, but there is no sign of malicious intent or obfuscation.
-
try: obj = eval(obj[-1]) except Exception: print ("Error processing object instance")likely benign Profiling script evals a generated instance expression from its own data file.Reasoning
eval is applied to the last line of profile-derived object data in a try block. This is unsafe if the profile input is attacker-controlled, but in context it reads as a utility parsing its own output, with no malicious indicators.
-
= = =likely benign Forwarding wrapper around __import__ that diffs sys.modules to track newly imported modules.Reasoning
This is a pass-through wrapper around __import__ that records which modules a call newly loads, a common pattern for dill's module tracking. The arguments come from the caller, not attacker-controlled data, and the file is an established serialization library.
-
= dellikely benign Temporarily swaps builtins.__import__ with a tracking wrapper and restores state afterward.Reasoning
The builtins.__import__ replacement is the temporary hook paired with the wrapper above, and the snippet shows cleanup of the builtins._ name. The patch is scoped to module-tracking, not to a payload or persistence mechanism.
-
# Use the calling frame's module = .. = # pragma: no coverlikely benign Uses inspect.currentframe to read the caller's module name for an object's __module__ attribute.Reasoning
Reading the calling frame's __name__ to set a pickled object's __module__ is a standard technique for determining the caller's module. The sys.exit/exec co-occurrence is a broad heuristic that does not fit this use.
-
returnlikely benign Wrapper around marshal.loads used to rebuild serialized code objects.Reasoning
dill's core job is serializing code objects, and marshal is the standard way to do that. The function deserializes data the library itself produced, so this is expected behavior for a pickler rather than a hidden dropper.
-
returnlikely benign Evaluates a repr string to reconstruct a serialized object during unpickling.Reasoning
_eval_repr evaluates repr strings produced during serialization, such as numpy dtype descriptions. The eval is a known weak point in deserialization, but the input is data dill wrote itself and the file is a serializer, not a loader for untrusted payloads.
-
returnlikely benign Eval of a repr string used to rebuild a serialized object.Reasoning
This is the eval finding for the same function as the one above. It is a legitimate reconstruction path, though eval on serialized input deserves a note.
-
= passlikely benign Dynamic __import__ of a module name recovered from pickled data, guarded by ImportError handling.Reasoning
Importing a module by name taken from serialized data is how unpickling locates classes and functions. The import is guarded by an ImportError handler, which is consistent with normal loader behavior.
-
= returnlikely benign Evaluates a constructed dotted-path expression to resolve an attribute from a repr.Reasoning
The eval builds an attribute-access expression from a repr string to locate an object by its qualified name. Its input comes from serialized data, so it is a known risk in deserialization code, but it reads as a lookup routine rather than an injected payload.
-
= = returnlikely benign Dynamic __import__ used to resolve dotted module and attribute paths when loading objects.Reasoning
This is the standard _import_module helper, which resolves dotted names and imports submodules with __import__. Its use is consistent with the library's purpose.
-
return return returnlikely benign Fallback __import__ inside the module-resolution helper.Reasoning
This is the fallback branch of the same module-resolution helper. The import name derives from the object being unpickled, which is the expected behavior.
-
returnlikely benign Final __import__ in the module-resolution helper, wrapped in exception handling.Reasoning
This is the final import in the same resolver, with ImportError, AttributeError and KeyError caught, which fits a best-effort loader.
-
# types module (part of CH 8) = = =likely benign Builds an empty code object to capture the CodeType type for a registry of built-in types.Reasoning
compile('','','exec') creates an empty code object solely to obtain the CodeType type for a lookup table of Python internal types. It executes nothing.
-
= = # file formats (CH 13) =likely benign Instantiates zlib compressor/decompressor objects to record their types in a registry.Reasoning
zlib.decompressobj() here creates a type reference for a table of standard library types, not a runtime payload. Nothing is decompressed from embedded data.
-
""" func = globals().get(name) if func is not None: _dill.__dict__[name] = funclikely benign Looks up a function by name in module globals and assigns it into the dill module dict.Reasoning
globals().get(name) to pull a function from module globals and copy it into the dill namespace is a normal dynamic lookup pattern in a serialization library's shim module; no sign of malicious payload.
-
dellikely benign Module-level exec generates type alias names from a static internal dict of object types.Reasoning
exec runs at import time, but the string is built from keys of a fixed internal objects dict to create type aliases (e.g. FunctionType = type(objects['FunctionType'])). The expression is non-literal but derived from trusted internal constants, so it is a benign if unusual metaprogramming idiom.
-
# this function # find_chain/find_backref_chain, likelylikely benign Uses sys._getframe to add the current frame's id to an ignore set during backref search.Reasoning
sys._getframe is used with an explicit comment to exclude helper frames from a reference-chain search during garbage-collection-based object tracing; standard debugging/introspection in dill.
-
# this function # find_chain/find_backref_chain, likelylikely benign Uses sys._getframe(1) to exclude the caller frame from backreference chain search.Reasoning
Same benign pattern: sys._getframe(1) is used with a comment to exclude the caller's frame from object-graph traversal.
-
= passlikely benign Re-imports top-level modules recorded in the session's __dill_imported_top_level metadata.Reasoning
__import__ on modname taken from a session-stored list of previously imported top-level modules; restores imports when loading a session. It is dynamic but operates on the module's own recorded names, not attacker-controlled execution. Loading untrusted session files is a genuine risk, but the code itself is ordinary restoration logic.
-
# the defaults are None and False =likely benign Reads a parameter value from locals() to check for conflicting deprecated arguments.Reasoning
locals()[par] reads a keyword-argument flag by name inside a deprecation-handling helper; ordinary Python introspection with no malicious characteristics.
-
): dellikely benign Re-exports globals into the _dill module namespace by name.Reasoning
Copies names from globals() onto the _dill module in a loop, a standard re-export pattern for aliasing module attributes.
-
#FIXME: unsafe = = # get code objects, for comparisonlikely benign Evaluates a reconstructed lambda expression to compare code objects during source introspection.Reasoning
eval of a lambda built from source-extracted lhs/rhs strings, used to recover code objects for comparison while reconstructing source; the FIXME acknowledges unsafety but inputs come from the local source being inspected, not untrusted remote data.
-
#FIXME: unsafe = = # get code objects, for comparisonlikely benign Evaluates a reconstructed lambda from parsed source to compare code objects.Reasoning
Same pattern as the sibling eval: builds a lambda from parsed source text for code-object comparison, with a known FIXME; expected for a source-inspection library.
-
, = , 0 = , =likely benign Evaluates an import-and-attribute assignment string to retrieve an object for source retrieval.Reasoning
eval of a generated assignment line that imports a module attribute to obtain an object for source lookup; operates on names from the inspected module, typical of dill's getsource machinery.
-
# _ = eval(getsource(f, force=True)) #XXX: safer but less robustlikely benign Executes generated importable source to reconstruct a named object in the given namespaces.Reasoning
exec of importable source generated by dill's own getimportable from the function being pickled, to recreate a named object; dynamic but intentional library behavior on local code.
-
#print(_str) #XXX: check if == obj? (name collision) #XXX: better top-down or bottom-up recursion? = #(or get all, then compare == obj?)likely benign Executes a generated import string while recursively resolving a dotted object name.Reasoning
exec of a generated import/source string during recursive name resolution for module-level objects; operates on names derived from the object being handled, with an XXX note about name collisions rather than malicious intent.
-
= = returnlikely benign Legitimate exec/eval of dill-generated source in a temp-object helper.Reasoning
This is dill's temp-file helper that reloads source it generated itself via dumpsource and exec/evals it to build a named object. The codecs import and exec/eval are the library's normal mechanism here, not a multi-stage payload.
-
= = returnlikely benign exec of a non-literal source string that dill itself produced.Reasoning
The exec runs source produced by dill's own dumpsource serializer inside a fresh local namespace. That is the expected dynamic-loading design of a serialization library, not attacker-supplied input.
-
= returnlikely benign eval of a formatted alias name in dill's temp-object helper.Reasoning
The eval evaluates an alias name formatted into a string and looked up in the local dict populated by the prior exec. It is part of the same self-generated-source round trip.
-
= = returnlikely benign Repeated exec of dill-generated source in a second helper.Reasoning
The same exec-of-generated-source pattern recurs in a second helper in this file, consistent with dill's serialization design. The snippet shows no network, download, or obfuscated payload.
-
= returnlikely benign Repeated eval of a formatted alias in dill's second temp helper.Reasoning
This is the matching eval of the alias after the second exec. It follows the same benign self-generated-source pattern as the other findings in this file.
-
= assert == #assert baditems(globals()) == [f] #XXXlikely benign Test code using inspect.currentframe to exercise dill's detection logic.Reasoning
This is a unit test calling inspect.currentframe to check that baditems detects frame objects. Frame introspection is the subject under test, not a malicious technique.
-
return =likely benign Test helper using eval on a hardcoded lambda string.Reasoning
This test helper evaluates a fixed lambda string with a supplied math namespace to check serialization of lambdas. The input is a controlled literal from the test, not external data.
-
assert .__name__ in assert in and inlikely benign Test reading module globals by name to verify session restoration.Reasoning
The test looks up module names through globals() to verify that session state was restored after dill round-trip. This is ordinary test assertion code.
-
assert is .__dict__ assert ==likely benign Test reading calendar globals by name to check session state.Reasoning
The globals() lookup checks that calendar attributes are present after session load. It is a standard verification step in a serialization test.
-
assert .__name__ == .__name__likely benign Test comparing globals against a copy after session round-trip.Reasoning
The loop compares globals values against a copied namespace after a session round-trip. This is expected assertion logic with no malicious indicators.
-
= assert ==likely benign Test exec of dumpsource output for locally defined functions.Reasoning
The test execs dumpsource output for functions it defines to confirm that source regeneration works. The code is test-local and self-generated.
-
assert ==likely benign Test exec of dumpsource output for a locally defined function.Reasoning
This exec of generated source for a locally defined test function matches the same self-verification pattern. Nothing in the snippet is external or obfuscated.
-
assert == assert ==likely benign Test exec of dumpsource output for another local test function.Reasoning
This exec of dumpsource output for the squared test function is part of the same source-regeneration test. It is benign test code.
-
assert == assert ==likely benign Test executes source text regenerated by dill's dumpsource to check round-trip behaviour.Reasoning
The exec call runs source generated by dill's own dumpsource helper inside a unit test, comparing results against the original functions. It is a self-referential round-trip test with no external input, so the dynamic execution is expected.
-
= assert ==likely benign Test execs import strings generated by dill's getimport to verify reconstructed functions.Reasoning
The exec call evaluates getimport output produced by dill's own helper from test-defined functions in a test namespace. This is standard round-trip verification and is not attacker-controlled.
-
assert ==likely benign Test execs dill-generated getimport strings and asserts on the resulting callables.Reasoning
Same pattern as the neighbouring findings: exec of dill-generated getimport strings inside a test, with assertions on the results. No external or hostile input is involved.
-
assert == assert ==likely benign Test execs getimport output for squared functions and compares results.Reasoning
Repeated test round-trip using dill's getimport on local functions, with exec in an isolated dict. The pattern is consistent with legitimate serialization testing.
-
assert ==likely benign Test execs getimport output for squared and Bar to verify reconstruction.Reasoning
Test code executing dill-generated import source for a function and a class, then checking behaviour. This is expected for a serialization library's test suite.
-
assert == assert ==likely benign Test execs getimport output for Bar and checks names match.Reasoning
The exec consumes getimport output for the Bar class within a test that compares names and behaviour. The input is generated locally, so there is no injection path.
-
assert ==likely benign Test execs getimport strings for Bar and tm.quad and asserts results.Reasoning
Test-only exec of dill-generated import strings, including for tm.quad, followed by assertions. Consistent with normal library testing.
-
assert == assert == #FIXME: wrong results for nested functions (e.g. tm.double_add, tm.quadratic)likely benign Test execs getimport output for tm.quad and compares results, with a known-issue FIXME.Reasoning
The exec call reconstructs tm.quad via dill's getimport in a test and compares results. The FIXME comment shows this is ordinary development code.
Reproduce This Scan
Run disclude locally to verify. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.
&&