PyPI / dill / 0.4.1

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+…⟩.

  1. critical dynamic-execution scripts/get_gprof:63:15

    `os.system` called on a non-literal command — runtime-determined shell invocation (ast pass, confidence 0.85)

        try:
            res = os.system(msg)
        except Exception:
            print ("Please verify install of 'gprof2dot' to view profile graphs")
    likely benign LLM, confidence 0.60 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.

  2. warn dynamic-execution scripts/get_gprof:43:9

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

        for line in obj[:-1]:
            exec(line)
        # one-line generation of an instance
        try:
    likely benign LLM, confidence 0.65 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.

  3. warn dynamic-execution scripts/get_gprof:46:15

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

        try:
            obj = eval(obj[-1])
        except Exception:
            print ("Error processing object instance")
    likely benign LLM, confidence 0.65 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.

  4. info critical → info by review dynamic-import dill/__diff.py:220:11

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

        before = set(sys.modules.keys())
        mod = __import__(*args, **kwds)
        after = set(sys.modules.keys()).difference(before)
        for m in after:
    likely benign LLM, confidence 0.80 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.

  5. info critical → info by review builtins-write dill/__diff.py:226:1

    `builtins.__import__ = ...` — patches a built-in for every importer of this module (ast pass, confidence 0.95)

    
    builtins.__import__ = _imp
    if hasattr(builtins, "_"):
        del builtins._
    likely benign LLM, confidence 0.70 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.

  6. info critical → info by review frame-introspection dill/_dill.py:213:31

    `inspect.currentframe` — call-stack frame introspection — file also calls `sys.exit`/`exec`/`eval` (anti-analysis shape) (ast pass, confidence 0.85)

                # Use the calling frame's module
                self.__module__ = inspect.currentframe().f_back.f_globals['__name__']
            else:
                self.__module__ = module_name # pragma: no cover
    likely benign LLM, confidence 0.90 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.

  7. info warn → info by review dynamic-execution dill/_dill.py:596:12

    `marshal.loads` deserializes Python bytecode from bytes — code-object sink (ast pass, confidence 0.75)

    def _unmarshal(string):
        return marshal.loads(string)
    
    def _load_type(name):
    likely benign LLM, confidence 0.85 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.

  8. info warn → info by review decoder-import-with-exec dill/_dill.py:980:12

    file imports decoder module(s) pickle, marshal and calls `exec`/`eval`/`compile` — multi-stage payload shape (ast pass, confidence 0.80)

    def _eval_repr(repr_str):
        return eval(repr_str)
    
    def _create_array(f, args, state, npdict=None):
    likely benign LLM, confidence 0.80 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.

  9. info warn → info by review dynamic-execution dill/_dill.py:980:12

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

    def _eval_repr(repr_str):
        return eval(repr_str)
    
    def _create_array(f, args, state, npdict=None):
    likely benign LLM, confidence 0.75 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.

  10. info critical → info by review dynamic-import dill/_dill.py:1012:26

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                try:
                    module = __import__(names[0])
                except ImportError:
                    pass
    likely benign LLM, confidence 0.85 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.

  11. info critical → info by review dynamic-execution dill/_dill.py:1038:16

    `eval` called on a constructed string (ast pass, confidence 0.80)

            attr = repr_str.split("'")[3]
            return eval(attr+'.__dict__["'+name+'"]')
        except Exception:
            try:
    likely benign LLM, confidence 0.80 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.

  12. info critical → info by review dynamic-import dill/_dill.py:1065:33

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                obj = items[-1]
                submodule = getattr(__import__(module, None, None, [obj]), obj)
                if isinstance(submodule, (ModuleType, type)):
                    return submodule
    likely benign LLM, confidence 0.85 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.

  13. info critical → info by review dynamic-import dill/_dill.py:1068:20

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                    return submodule
                return __import__(import_name, None, None, [obj])
            else:
                return __import__(import_name)
    likely benign LLM, confidence 0.85 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.

  14. info critical → info by review dynamic-import dill/_dill.py:1070:20

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            else:
                return __import__(import_name)
        except (ImportError, AttributeError, KeyError):
            if safe:
    likely benign LLM, confidence 0.85 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.

  15. info warn → info by review decoder-import-with-exec dill/_objects.py:239:17

    file imports decoder module(s) codecs, zlib, gzip, bz2 and calls `exec`/`eval`/`compile` — multi-stage payload shape (ast pass, confidence 0.80)

    # types module (part of CH 8)
    a['CodeType'] = compile('','','exec')
    a['DictProxyType'] = type.__dict__
    a['DictProxyType2'] = _newclass.__dict__
    likely benign LLM, confidence 0.90 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.

  16. info warn → info by review decoder-decompress-payload dill/_objects.py:460:27

    file imports decoder module(s) codecs, zlib, gzip, bz2 and calls `.decompress()` — embedded payload decompressed at runtime (ast pass, confidence 0.75)

    x['ZlibCompressType'] = zlib.compressobj()
    x['ZlibDecompressType'] = zlib.decompressobj()
    # file formats (CH 13)
    x['CSVReaderType'] = csv.reader(_cstrI)
    likely benign LLM, confidence 0.90 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.

  17. info warn → info by review dynamic-attribute dill/_shims.py:174:12

    reach-by-name through `globals.get` (ast pass, confidence 0.60)

        """
        func = globals().get(name)
        if func is not None:
            _dill.__dict__[name] = func
    likely benign LLM, confidence 0.90 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.

  18. info critical → info by review dynamic-execution dill/objtypes.py:18:5

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    for _type in objects.keys():
        exec("%s = type(objects['%s'])" % (_type,_type))
        
    del objects
    likely benign LLM, confidence 0.90 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.

  19. info warn → info by review frame-introspection dill/pointers.py:93:19

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

        ignore.add(id(ignore))
        ignore.add(id(sys._getframe()))  # this function
        ignore.add(id(sys._getframe(1))) # find_chain/find_backref_chain, likely
        gc.collect()
    likely benign LLM, confidence 0.90 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.

  20. info warn → info by review frame-introspection dill/pointers.py:94:19

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

        ignore.add(id(sys._getframe()))  # this function
        ignore.add(id(sys._getframe(1))) # find_chain/find_backref_chain, likely
        gc.collect()
        while queue:
    likely benign LLM, confidence 0.95 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.

  21. info critical → info by review dynamic-import dill/session.py:125:42

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            for modname, name in main_module.__dict__.pop('__dill_imported_top_level'):
                main_module.__dict__[name] = __import__(modname)
        except KeyError:
            pass
    likely benign LLM, confidence 0.90 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.

  22. info warn → info by review dynamic-attribute dill/session.py:226:16

    reach-by-name through `locals` (ast pass, confidence 0.60)

                warnings.warn(message + ".", PendingDeprecationWarning)
                if locals()[par]:  # the defaults are None and False
                    raise TypeError("both %r and %r arguments were used" % (par, old_par))
        refimported = kwds.pop('byref', refimported)
    likely benign LLM, confidence 0.90 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.

  23. info warn → info by review dynamic-attribute dill/session.py:611:26

    reach-by-name through `globals` (ast pass, confidence 0.60)

    ):
        setattr(_dill, name, globals()[name])
    del name
    likely benign LLM, confidence 0.90 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.

  24. info warn → info by review dynamic-execution dill/source.py:60:13

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

        try: #FIXME: unsafe
            _ = eval("lambda %s : %s" % (lhs,rhs), globals(),locals())
        except Exception: _ = dummy
        # get code objects, for comparison
    likely benign LLM, confidence 0.90 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.

  25. info warn → info by review dynamic-execution dill/source.py:82:18

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

            try: #FIXME: unsafe
                _f = eval("lambda %s : %s" % (_lhs,_rhs), globals(),locals())
            except Exception: _f = dummy
            # get code objects, for comparison
    likely benign LLM, confidence 0.90 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.

  26. info warn → info by review dynamic-execution dill/source.py:397:23

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

                    lines, lnum = ["%s = __import__('%s', fromlist=['%s']).%s\n" % (name,module,name,name)], 0
                    obj = eval(lines[0].lstrip(name + ' = '))
                    lines, lnum = getsourcelines(obj, enclosing=enclosing)
    likely benign LLM, confidence 0.85 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.

  27. info warn → info by review dynamic-execution dill/source.py:543:13

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

                # _ = eval(getsource(f, force=True)) #XXX: safer but less robust
                exec(getimportable(f, alias='_'), __globals__, __locals__)
            except Exception:
                raise ImportError('cannot import name ' + f.__name__)
    likely benign LLM, confidence 0.85 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.

  28. info warn → info by review dynamic-execution dill/source.py:713:14

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

           #print(_str)
            try: exec(_str) #XXX: check if == obj? (name collision)
            except ImportError: #XXX: better top-down or bottom-up recursion?
                _head = head.rsplit(".",1)[0] #(or get all, then compare == obj?)
    likely benign LLM, confidence 0.85 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.

  29. info warn → info by review decoder-import-with-exec dill/temp.py:71:5

    file imports decoder module(s) codecs and calls `exec`/`eval`/`compile` — multi-stage payload shape (ast pass, confidence 0.80)

        local = {}
        exec(source, local)
        _ = eval("%s" % alias, local)
        return _
    likely benign LLM, confidence 0.85 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.

  30. info warn → info by review dynamic-execution dill/temp.py:71:5

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

        local = {}
        exec(source, local)
        _ = eval("%s" % alias, local)
        return _
    likely benign LLM, confidence 0.80 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.

  31. info warn → info by review dynamic-execution dill/temp.py:72:9

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

        exec(source, local)
        _ = eval("%s" % alias, local)
        return _
    likely benign LLM, confidence 0.85 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.

  32. info warn → info by review dynamic-execution dill/temp.py:220:5

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

        local = {}
        exec(source, local)
        _ = eval("%s" % alias, local)
        return _
    likely benign LLM, confidence 0.80 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.

  33. info warn → info by review dynamic-execution dill/temp.py:221:9

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

        exec(source, local)
        _ = eval("%s" % alias, local)
        return _
    likely benign LLM, confidence 0.85 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.

  34. info warn → info by review frame-introspection dill/tests/test_detect.py:19:9

    `inspect.currentframe` — call-stack frame introspection (ast pass, confidence 0.70)

    def test_bad_things():
        f = inspect.currentframe()
        assert baditems(f) == [f]
        #assert baditems(globals()) == [f] #XXX
    likely benign LLM, confidence 0.95 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.

  35. info warn → info by review dynamic-execution dill/tests/test_module.py:72:12

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

    def get_lambda(str, **kwarg):
        return eval(str, kwarg, None)
    
    obj = get_lambda('lambda x: math.exp(x)', math=math)
    likely benign LLM, confidence 0.95 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.

  36. info warn → info by review dynamic-attribute dill/tests/test_session.py:42:24

    reach-by-name through `globals` (ast pass, confidence 0.60)

                for obj in ('json', 'url', 'local_mod', 'sax', 'dom'):
                    assert globals()[obj].__name__ in sys.modules
                assert 'calendar' in sys.modules and 'cmath' in sys.modules
                import calendar, cmath
    likely benign LLM, confidence 0.93 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.

  37. info warn → info by review dynamic-attribute dill/tests/test_session.py:47:24

    reach-by-name through `globals` (ast pass, confidence 0.60)

                for obj in ('Calendar', 'isleap'):
                    assert globals()[obj] is sys.modules['calendar'].__dict__[obj]
                assert __main__.day_name.__module__ == 'calendar'
                if refimported:
    likely benign LLM, confidence 0.93 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.

  38. info warn → info by review dynamic-attribute dill/tests/test_session.py:126:20

    reach-by-name through `globals` (ast pass, confidence 0.60)

            for obj in ('json', 'url', 'local_mod', 'sax', 'dom'):
                assert globals()[obj].__name__ == globals_copy[obj].__name__
    
            for obj in ('x', 'empty', 'names'):
    likely benign LLM, confidence 0.93 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.

  39. info warn → info by review dynamic-execution dill/tests/test_sources.py:118:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      local = {}
      exec(ds.dumpsource(add, alias='raw'), {}, local)
      exec(ds.dumpsource(ts.add, alias='mod'), {}, local)
      assert local['raw'](1,2) == local['mod'](1,2)
    likely benign LLM, confidence 0.92 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.

  40. info warn → info by review dynamic-execution dill/tests/test_sources.py:119:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      exec(ds.dumpsource(add, alias='raw'), {}, local)
      exec(ds.dumpsource(ts.add, alias='mod'), {}, local)
      assert local['raw'](1,2) == local['mod'](1,2)
      exec(ds.dumpsource(squared, alias='raw'), {}, local)
    likely benign LLM, confidence 0.92 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.

  41. info warn → info by review dynamic-execution dill/tests/test_sources.py:121:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      assert local['raw'](1,2) == local['mod'](1,2)
      exec(ds.dumpsource(squared, alias='raw'), {}, local)
      exec(ds.dumpsource(ts.squared, alias='mod'), {}, local)
      assert local['raw'](3) == local['mod'](3)
    likely benign LLM, confidence 0.92 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.

  42. info warn → info by review dynamic-execution dill/tests/test_sources.py:122:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      exec(ds.dumpsource(squared, alias='raw'), {}, local)
      exec(ds.dumpsource(ts.squared, alias='mod'), {}, local)
      assert local['raw'](3) == local['mod'](3)
      assert ds._wrap(add)(1,2) == ds._wrap(ts.add)(1,2)
    likely benign LLM, confidence 0.92 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.

  43. info warn → info by review dynamic-execution dill/tests/test_sources.py:152:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      local = {}
      exec(ds.getimport(add, alias='raw'), {}, local)
      exec(ds.getimport(ts.add, alias='mod'), {}, local)
      assert local['raw'](1,2) == local['mod'](1,2)
    likely benign LLM, confidence 0.92 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.

  44. info warn → info by review dynamic-execution dill/tests/test_sources.py:153:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      exec(ds.getimport(add, alias='raw'), {}, local)
      exec(ds.getimport(ts.add, alias='mod'), {}, local)
      assert local['raw'](1,2) == local['mod'](1,2)
      exec(ds.getimport(squared, alias='raw'), {}, local)
    likely benign LLM, confidence 0.92 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.

  45. info warn → info by review dynamic-execution dill/tests/test_sources.py:155:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      assert local['raw'](1,2) == local['mod'](1,2)
      exec(ds.getimport(squared, alias='raw'), {}, local)
      exec(ds.getimport(ts.squared, alias='mod'), {}, local)
      assert local['raw'](3) == local['mod'](3)
    likely benign LLM, confidence 0.92 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.

  46. info warn → info by review dynamic-execution dill/tests/test_sources.py:156:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      exec(ds.getimport(squared, alias='raw'), {}, local)
      exec(ds.getimport(ts.squared, alias='mod'), {}, local)
      assert local['raw'](3) == local['mod'](3)
      exec(ds.getimport(Bar, alias='raw'), {}, local)
    likely benign LLM, confidence 0.92 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.

  47. info warn → info by review dynamic-execution dill/tests/test_sources.py:158:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      assert local['raw'](3) == local['mod'](3)
      exec(ds.getimport(Bar, alias='raw'), {}, local)
      exec(ds.getimport(ts.Bar, alias='mod'), {}, local)
      assert ds.getname(local['raw']) == ds.getname(local['mod'])
    likely benign LLM, confidence 0.92 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.

  48. info warn → info by review dynamic-execution dill/tests/test_sources.py:159:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      exec(ds.getimport(Bar, alias='raw'), {}, local)
      exec(ds.getimport(ts.Bar, alias='mod'), {}, local)
      assert ds.getname(local['raw']) == ds.getname(local['mod'])
      exec(ds.getimport(tm.quad, alias='mod'), {}, local)
    likely benign LLM, confidence 0.92 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.

  49. info warn → info by review dynamic-execution dill/tests/test_sources.py:161:3

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

      assert ds.getname(local['raw']) == ds.getname(local['mod'])
      exec(ds.getimport(tm.quad, alias='mod'), {}, local)
      assert local['mod']()(sum)([1,2,3]) == tm.quad()(sum)([1,2,3])
      #FIXME: wrong results for nested functions (e.g. tm.double_add, tm.quadratic)
    likely benign LLM, confidence 0.92 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.

cargo install disclude --version 4.1.0
git clone https://github.com/uqfoundation/dill dill && cd dill
git checkout 0.4.1
disclude scan --severity info --diff 0.4.0 .