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
- 38.1 s
- LLM review
- Reviewed by claude-haiku-5-5 (Anthropic): 49 of 49 warn and critical signals; 46 demoted to info.
- Disclude version
- 4.1.0
- Scanned (UTC)
- 2026-10-22 05:51
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 Shell invocation of a gprof2dot-based graph command in a profiling script, with an install-hint error message.Reasoning
os.system runs a runtime-built message that is apparently a shell command for rendering profile graphs with gprof2dot, and the except branch prints an install hint for that tool. That is a common, legitimate pattern for a dependent-tool invocation. Because the command string is not shown, it could be built from untrusted data, so the critical severity is not fully explained by the snippet.
-
for line in obj[:-1]: exec(line) # one-line generation of an instance try:likely benign Legacy profiling helper that uses exec on lines of a stored object to regenerate an instance.Reasoning
The exec call runs lines read from a stored object representation, with comments describing one-line generation of an instance. That reads as a legacy self-serialization or code-generation idiom in a profiling helper, not a dropper. The snippet does not show where the input comes from, so an untrusted source cannot be ruled out, which keeps confidence moderate.
-
try: obj = eval(obj[-1]) except Exception: print ("Error processing object instance")likely benign eval of the last element of a stored object during instance reconstruction in a profiling script.Reasoning
eval is applied to the last element of the same stored object, inside a try block that prints a processing error. It matches the same self-deserialization pattern as the exec finding and has no network, encoding, or stealth elements. The input source is unshown, so the verdict stays moderate.
-
= = =likely benign Wrapper that forwards arguments to __import__ to record which modules a call loads.Reasoning
__import__ with forwarded args is a generic import helper in a diagnostic module that tracks newly imported modules. It is not hiding a payload.
-
= dellikely benign Temporarily replaces builtins.__import__ with a tracking wrapper for module-diff analysis.Reasoning
Assigning builtins.__import__ is a global side effect and is worth noting, but in dill's diagnostic helper it looks like a temporary hook that is restored (builtins._ cleanup), not a malicious persistent backdoor.
-
# Use the calling frame's module = .. = # pragma: no coverlikely benign Reads the calling frame's module name to set __module__ on a dill object.Reasoning
inspect.currentframe().f_back.f_globals is used to get the caller's module name for a pickled type. The sys.exit/exec co-occurrence is a file-level heuristic and does not apply to this use.
-
returnlikely benign Helper that unmarshals Python code-object bytes during dill deserialization.Reasoning
dill's core job is serializing code objects, so marshal.loads of bytes it produced itself is expected. It is a known sink but the data flow is the library's normal design.
-
returnlikely benign Evaluates a stored repr string to reconstruct an object during loading.Reasoning
eval of a repr string restores numpy array state inside dill's own serialization. The multi-stage heuristic is triggered by the library's normal pickle and marshal imports.
-
returnlikely benign eval on a repr string used to rebuild a serialized value.Reasoning
eval of a repr string is a real code-execution sink for untrusted pickles. In dill it reconstructs trusted serialized data, which is a known and documented trade-off rather than hidden malicious intent.
-
= passlikely benign Imports a module by name while resolving a serialized object reference.Reasoning
Dynamic __import__ of a module name from a serialized reference is how dill resolves module-level objects. The ImportError handling is ordinary.
-
= returnlikely benign Evaluates a constructed attribute path to locate an object for unpickling.Reasoning
The eval builds an attribute path from a repr and a name to fetch __dict__ entries. This is dill's attribute-lookup fallback, and the input is serialized metadata. Eval of constructed strings is a risk but matches normal library behavior here.
-
= = returnlikely benign Imports a submodule dynamically to resolve a dotted object path.Reasoning
Dynamic import with a fromlist is standard for resolving dotted module paths during object lookup in dill.
-
return return returnlikely benign Returns the object resolved via dynamic import from a dotted name.Reasoning
Same dynamic import resolution pattern as the nearby lines, returning the target object or falling back.
-
returnlikely benign Fallback dynamic import that handles ImportError, AttributeError and KeyError.Reasoning
Fallback import within an exception handler for object lookup. It is ordinary error-handling code in a serialization library.
-
# types module (part of CH 8) = = =likely benign Builds a table of built-in Python type objects, including a CodeType prototype.Reasoning
compile('','','exec') builds a CodeType prototype and the other lines capture built-in type dicts for a registry. The codecs/zlib import is incidental to the type table.
-
= = # file formats (CH 13) =likely benign Registers zlib compress/decompress object types in a built-in type table.Reasoning
zlib.decompressobj() here creates a type-table entry for the zlib module's type, not a decompression of an embedded payload.
-
""" func = globals().get(name) if func is not None: _dill.__dict__[name] = funclikely benign Looks up a shim function by name from module globals and registers it on dill.Reasoning
globals().get(name) looks up a shim function by name in the module's own globals to re-export it into dill. It is a local lookup with no external input.
-
dellikely benign Creates module-level type alias names from a fixed dictionary of built-in types.Reasoning
exec runs a format string built from keys of a fixed internal dict to create type aliases at import. The keys are hardcoded type names, so there is no attacker-controlled input.
-
# this function # find_chain/find_backref_chain, likelylikely benign Uses sys._getframe to ignore its own frames when tracing object back-references.Reasoning
sys._getframe is used to exclude the current function's own frames from a reference-chain search. It is debugging and GC bookkeeping, not anti-analysis.
-
# this function # find_chain/find_backref_chain, likelylikely benign Frame introspection in dill's backref chain finder to exclude its own frames from the search.Reasoning
sys._getframe used in a reference-chain search utility in dill's pointers module to ignore frames during garbage-collection-based backref search; a standard introspection idiom for this purpose.
-
= passlikely benign Re-imports top-level modules recorded in a dill session when loading it.Reasoning
__import__ of module names recorded earlier in __dill_imported_top_level during session restore; this is the expected mechanism for re-importing modules a pickled session depends on, the names come from dill's own bookkeeping.
-
# the defaults are None and False =likely benign Reads local argument values by name to check deprecated keyword usage.Reasoning
locals() lookup of parameter names in a deprecation-handling helper; ordinary Python introspection of its own arguments, not hidden behavior.
-
): dellikely benign Copies names from module globals onto the _dill module via setattr.Reasoning
globals() lookup used in a loop to re-export names into the _dill module namespace, a plain module-population idiom with no concealment.
-
#FIXME: unsafe = = # get code objects, for comparisonlikely benign Evaluates reconstructed lambda source text to recover code objects for comparison.Reasoning
eval of a lambda built from source-recovered lhs/rhs strings inside dill's source-extraction code; the FIXME acknowledges the unsafe pattern, but the input is code dill itself reconstructs from local source, not attacker-controlled network data.
-
#FIXME: unsafe = = # get code objects, for comparisonlikely benign Evaluates reconstructed lambda source to obtain a function for comparison.Reasoning
Same pattern as the sibling eval in dill's source module: evaluating reconstructed lambda text for code-object comparison, with a known FIXME; a legitimate if unsafe design.
-
, = , 0 = , =likely benign Evaluates a generated import/assignment line to resolve an object's source.Reasoning
eval of a constructed assignment line to resolve an object for source lookup; dill generates the string from module and name metadata of the object being pickled, which is a known design rather than a concealed payload.
-
# _ = eval(getsource(f, force=True)) #XXX: safer but less robustlikely benign Executes generated importable source to recreate a function in a namespace.Reasoning
exec of importable source generated by dill's getimportable for a function being reconstructed; the code is derived from the object itself, consistent with dill's documented behavior.
-
#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 statement to resolve a dotted name.Reasoning
exec of a generated import string for name resolution, with an XXX comment on name collisions; a source-resolution fallback in a serialization library.
-
= = returnlikely benign Execs generated source into a local namespace and evaluates an alias from it.Reasoning
Temp-file helper in dill that execs source and evals an alias; the codecs-import plus exec co-occurrence is a payload-shape heuristic, but here the source is the dill-generated module text used for loading temporary pickled objects, and no decode-and-run chain of attacker data is shown.
-
= = returnlikely benign Execs internally generated source into a local dict in dill's temp utilities.Reasoning
Same exec call as the sibling finding in dill's temp helper; the source is internally generated for loading dill objects, consistent with library behavior.
-
= returnlikely benign Evaluates an alias name against the local namespace after exec.Reasoning
eval of an alias name in the local namespace populated by the preceding exec; a lookup pattern within dill's own helper.
-
= = returnlikely benign Execs internally generated source into a local dict in dill's temp utilities.Reasoning
Repeats the same exec in a second temp utility in dill; consistent with internal source loading for serialized objects.
-
= returnlikely benign Evaluates an alias name against the local namespace after exec.Reasoning
Same alias eval following exec as the sibling in dill's temp module; legitimate lookup pattern.
-
= assert == #assert baditems(globals()) == [f] #XXXlikely benign Test helper obtains its current frame to verify baditems detection.Reasoning
Test function inspecting its own frame via inspect.currentframe to check baditems detection; standard test code.
-
return =likely benign Test helper evaluates a lambda expression with math provided, for module pickling tests.Reasoning
Test helper evaluating a fixed lambda string with a restricted namespace of math; test scaffolding in dill's test suite with no attacker input.
-
assert .__name__ in assert in and inlikely benign Test code looks up imported module objects in globals() by name to verify they are in sys.modules.Reasoning
The loop reads module globals by name inside a test that checks session save/restore of imported modules. This is ordinary test introspection with no decoding, network access or execution of untrusted data.
-
assert is .__dict__ assert ==likely benign Test checks that globals() names match the calendar module's attributes after reloading a session.Reasoning
The test compares globals() entries against a standard library module's __dict__ after a session round trip. This is a normal assertion pattern in a serialization test suite.
-
assert .__name__ == .__name__likely benign Test compares module objects in globals() against a copied globals dict after session restore.Reasoning
The loop compares module names between the live globals and a saved copy, a routine check that session restoration preserved the imported modules.
-
= assert ==likely benign Test execs source generated by ds.dumpsource for local functions and checks the output matches.Reasoning
The exec runs source text generated by dill's own dumpsource() from functions defined in the test file, then compares results. It is a self-contained round-trip test with no external input.
-
assert ==likely benign Test execs dumpsource-generated source for the add function and asserts equal results.Reasoning
Same pattern as the neighbouring exec calls: dill's dumpsource output for functions defined in the test is executed into a local namespace and checked against the originals.
-
assert == assert ==likely benign Test execs dumpsource output for squared and compares results with the module version.Reasoning
The exec consumes dill's own generated source for test functions, and the assertion checks behaviour. No untrusted input or decode step is involved.
-
assert == assert ==likely benign Test execs dumpsource output for squared, then checks a wrapped add call.Reasoning
This exec runs dill-generated source for a test function, and the assertion checks the wrapper behaviour. It is consistent with the rest of the test module.
-
= assert ==likely benign Test execs getimport-generated import source for add and compares results.Reasoning
The exec runs source produced by dill's getimport() for functions defined in the test. This is a round-trip check of import-source generation.
-
assert ==likely benign Test execs getimport output for add with a module-level comparison.Reasoning
The exec consumes dill's own getimport output for a test function, and the assertion checks equality. No untrusted data is involved.
-
assert == assert ==likely benign Test execs getimport output for squared and checks the result.Reasoning
This exec runs getimport-generated source for a test function in a fixed local namespace. It is a normal test of dill's source tooling.
-
assert ==likely benign Test execs getimport output for squared with a comparison against the module version.Reasoning
The exec runs dill-generated import source for squared, followed by an assertion on the result. It is a standard round-trip test.
-
assert == assert ==likely benign Test execs getimport output for class Bar and compares getname results.Reasoning
The exec consumes getimport output for the Bar class defined in the test, then compares names. This is consistent with the test's purpose.
-
assert ==likely benign Test execs getimport output for tm.quad after checking Bar names.Reasoning
This exec runs dill-generated import source for tm.quad in a local namespace. The source comes from the library itself, not from external input.
-
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 checks nested-function results against the original.Reasoning
The exec runs getimport output for tm.quad and the assertion checks nested-function results. The FIXME note shows this is a known correctness issue, not a sign of malice.
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.
&&