Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
raw_req,
(req for req in reqs if for_extra(req) and eval(req, extra=extra)),
)
)
likely benign
LLM, confidence 0.60
Evaluates requirement marker expressions with extra context while converting wheel metadata to requirements.
Reasoning
The call eval(req, extra=extra) inside a generator is unusual, since real marker evaluation usually goes through the packaging marker API. The snippet is short and this is likely a local helper or a truncated view of marker evaluation on requirement strings. Nothing shows decoding or fetching external code, so benign is the best reading, but the snippet alone leaves some doubt.
-
`.pth` line that Python's `site` executes at every interpreter start (ast pass, confidence 0.70)
import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim();
likely benign
LLM, confidence 0.85
Standard setuptools distutils-precedence .pth line that enables the _distutils_hack shim at interpreter start.
Reasoning
This is the standard setuptools .pth shim. It only checks SETUPTOOLS_USE_DISTUTILS and calls _distutils_hack.add_shim(), with no decoding, network access or process spawning, so it matches the legitimate pattern for this file.
-
`os.popen` called on a non-literal command — runtime-determined shell invocation (ast pass, confidence 0.85)
out = os.popen(q_cmd)
try:
binary_rpms = []
likely benign
LLM, confidence 0.80
Runs a constructed rpm query command during RPM build packaging.
Reasoning
os.popen is used to run an rpm query command built from the packaging configuration. The command is runtime-determined but comes from build metadata, which is expected for an RPM packaging command.
-
`subprocess.getoutput` called with a literal shell command (ast pass, confidence 0.70)
vendor_hook = subprocess.getoutput('rpm --eval %{__os_install_post}')
likely benign
LLM, confidence 0.90
Fixed-literal rpm --eval call that reads a macro during RPM packaging.
Reasoning
The command is a fixed literal 'rpm --eval %{__os_install_post}' used to read the vendor macro. It is a standard RPM-building step with no untrusted input.
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
expected = '"static", "shared", "dylib", "xcode_stub"'
if lib_type not in eval(expected):
raise ValueError(f"'lib_type' must be {expected}")
fmt = getattr(self, lib_type + "_lib_format")
likely benign
LLM, confidence 0.90
eval of a hardcoded tuple string listing valid library types.
Reasoning
eval is applied to a fixed string literal of library type names defined a few lines above. No external input reaches it, so it is a benign idiom.
-
`exec` called on a non-literal expression (ast pass, confidence 0.70)
code = f.read().replace(r'\r\n', r'\n')
exec(code, g) finally:
sys.argv = save_argv
likely benign
LLM, confidence 0.90
Executes the project's setup script as part of the distutils setup() runner.
Reasoning
This is the distutils setup-script runner, which executes the user's setup.py by design. The comment notes this, and the exec is the expected behavior of the tool.
-
`__import__` called on a non-literal expression (ast pass, confidence 0.70)
try:
__import__(module_name)
module = sys.modules[module_name]
except ImportError:
likely benign
LLM, confidence 0.90
Dynamic import of a distutils command module by name.
Reasoning
__import__ loads a command or module by name during option and command resolution. The module names come from distutils' own command registry, which is normal plugin loading.
-
`compile` called on a non-literal expression (ast pass, confidence 0.70)
log.info("byte-compiling %s to %s", file, cfile_base)
compile(file, cfile, dfile)
else:
log.debug("skipping byte-compilation of %s to %s", file, cfile_base)
likely benign
LLM, confidence 0.90
Byte-compiles Python source files during installation.
Reasoning
This is the standard byte-compilation helper that compiles Python source files during install. The compile call is the expected operation in that context.
-
file imports decoder module(s) zlib, bz2, lzma, gzip and calls `.decompress()` — embedded payload decompressed at runtime (ast pass, confidence 0.75)
likely benign
LLM, confidence 0.90
Streaming zlib decompression within the vendored tarfile implementation.
Reasoning
This is the backported tarfile module, which uses zlib decompressobj to read compressed tar streams. Decompression is its core function, not a hidden payload.
-
`eval` called on a non-literal expression (ast pass, confidence 0.70)
try:
return eval(use)
except TypeError:
return replace
likely benign
LLM, confidence 0.70
eval of a caller-supplied expression in a vendored jaraco functools helper.
Reasoning
eval runs a 'use' argument in a helper that converts a value through an expression. The vendored jaraco helper is generic, but the snippet doesn't show where 'use' comes from, so some doubt remains.
-
`compile` called on a non-literal expression (ast pass, confidence 0.70)
try:
compile(python_expression, "", "eval")
except SyntaxError:
message = f"Invalid license expression: {raw_license_expression!r}"
likely benign
LLM, confidence 0.90
Compiles a license expression purely to validate its syntax.
Reasoning
compile with mode 'eval' is used only to syntax-check a license expression and catch SyntaxError. It compiles without executing, so it is a validation step.
-
`exec` called on a non-literal expression (ast pass, confidence 0.70)
try:
exec(code, locals()) except SystemExit as e:
if e.code:
likely benign
LLM, confidence 0.90
Executes setup.py code inside the PEP 517 build backend.
Reasoning
This is the PEP 517 build backend, which executes the project's setup.py as part of building. Running setup code is the purpose of this module.
-
`marshal.load` deserializes Python bytecode from bytes — code-object sink (ast pass, confidence 0.75)
f.read(skip)
code = marshal.load(f)
f.close()
safe = True
likely benign
LLM, confidence 0.80
Loads a code object from a module file while building an egg.
Reasoning
marshal.load reads bytecode from an existing module file during egg construction, such as reading a .pyc header or code object for analysis. This is normal for the egg-building code path.
-
`inspect.getouterframes` — call-stack frame introspection (ast pass, confidence 0.70)
frames = inspect.getouterframes(run_frame)
for frame in frames[2:4]:
(caller,) = frame[:1]
likely benign
LLM, confidence 0.85
Inspects the call stack to identify the setup-script caller during install.
Reasoning
inspect.getouterframes is used to find the calling setup script frame so install can reason about its caller. Frame introspection like this is a known setuptools pattern and has no malicious effect.
-
line length 1035 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".build-system must be object", value=data__buildsystem, name="" + (name_prefix or "data") + ".build-system", definition={'type': 'object', 'description': 'Table used to store build-related data', 'additionalProperties': False, 'properties':
-
line length 792 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".dependency-groups must be object", value=data__dependencygroups, name="" + (name_prefix or "data") + ".dependency-groups", definition={'type': 'object', 'description': 'Dependency groups following PEP 735', 'additionalProperties': False, 'p
-
line length 891 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".package-dir must be object", value=data__packagedir, name="" + (name_prefix or "data") + ".package-dir", definition={'$$description': [':class:`dict`-like structure mapping from package names to directories where their', 'code can be found.
-
line length 968 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".package-data must be object", value=data__packagedata, name="" + (name_prefix or "data") + ".package-data", definition={'$$description': ['Mapping from package names to lists of glob patterns.', 'Usually this option is not needed when using
-
line length 934 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".exclude-package-data must be object", value=data__excludepackagedata, name="" + (name_prefix or "data") + ".exclude-package-data", definition={'$$description': ['Mapping from package names to lists of glob patterns that should be excluded',
-
line length 1720 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".ext-modules must be array", value=data__extmodules, name="" + (name_prefix or "data") + ".ext-modules", definition={'description': 'Extension modules to be compiled by setuptools', 'type': 'array', 'items': {'$id': '#/definitions/ext-module
-
line length 791 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".data-files must be object", value=data__datafiles, name="" + (name_prefix or "data") + ".data-files", definition={'$$description': ['``dict``-like structure where each key represents a directory and', 'the value is a list of glob patterns t
-
line length 1584 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + " must be object", value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/ext-module', 'title': 'Extension module', 'description': 'Parameters to construct a :class:`setuptools.Extension` object', 'type': 'object', 'req
-
line length 1643 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + " must contain " + (str(sorted(data__missing_keys)) + " properties"), value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/ext-module', 'title': 'Extension module', 'description': 'Parameters to construct a :class
-
line length 1636 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/ext-module', 'title': 'Extension module', 'description': 'Parameters to construct a :class:`setuptools.Extens
-
line length 1230 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + " must be object", value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/find-directive', 'title': "'find:' directive", 'type': 'object', 'additionalProperties': False, 'properties': {'find': {'type': 'object', '$$desc
-
line length 1110 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".find must be object", value=data__find, name="" + (name_prefix or "data") + ".find", definition={'type': 'object', '$$description': ['Dynamic `package discovery', '<https://setuptools.pypa.io/en/latest/userguide/package_discovery.html>`_.']
-
line length 1282 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/find-directive', 'title': "'find:' directive", 'type': 'object', 'additionalProperties': False, 'properties':
-
line length 1502 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".readme must be valid exactly by one definition" + (" (" + str(data__readme_one_of_count12) + " matches found)"), value=data__readme, name="" + (name_prefix or "data") + ".readme", definition={'$$description': ['`Full/detailed description of
-
line length 935 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".license must be valid exactly by one definition" + (" (" + str(data__license_one_of_count14) + " matches found)"), value=data__license, name="" + (name_prefix or "data") + ".license", definition={'description': '`Project license <https://pe
-
line length 963 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".authors must be array", value=data__authors, name="" + (name_prefix or "data") + ".authors", definition={'type': 'array', 'items': {'$id': '#/definitions/author', 'title': 'Author or Maintainer', '$comment': 'https://peps.python.org/pep-062
-
line length 920 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".maintainers must be array", value=data__maintainers, name="" + (name_prefix or "data") + ".maintainers", definition={'type': 'array', 'items': {'$id': '#/definitions/author', 'title': 'Author or Maintainer', '$comment': 'https://peps.python
-
line length 837 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + ".dynamic[{data__dynamic_x}]".format(**locals()) + " must be one of ['version', 'description', 'readme', 'requires-python', 'license', 'license-files', 'authors', 'maintainers', 'keywords', 'classifiers', 'urls', 'scripts', 'gui-scrip
-
line length 968 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + " must be object", value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/entry-point-group', 'title': 'Entry-points', 'type': 'object', '$$description': ['Entry-points are grouped together to indicate what sort of capa
-
line length 1020 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + " must not contain "+str(data_keys)+" properties", value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/entry-point-group', 'title': 'Entry-points', 'type': 'object', '$$description': ['Entry-points are grouped to
-
line length 1011 characters (raw pass, confidence 0.50)
raise JsonSchemaValueException("" + (name_prefix or "data") + " must be named by propertyName definition", value=data, name="" + (name_prefix or "data") + "", definition={'$id': '#/definitions/entry-point-group', 'title': 'Entry-points', 'type': 'object', '$$description': ['Entry-points are grouped toge
-
`marshal.load` deserializes Python bytecode from bytes — code-object sink (ast pass, confidence 0.75)
f.read(8) code = marshal.load(f)
elif kind == PY_FROZEN:
code = _imp.get_frozen_object(module, paths)
likely benign
LLM, confidence 0.90
Loads module bytecode from a file for dependency analysis.
Reasoning
marshal.load reads the bytecode of a module being inspected for dependency detection, matching the code-object loading that setuptools' depends module does by design.
-
file imports decoder module(s) marshal and calls `exec`/`eval`/`compile` — multi-stage payload shape (ast pass, confidence 0.80)
elif kind == PY_SOURCE:
code = compile(f.read(), path, 'exec')
else:
likely benign
LLM, confidence 0.85
Compiles a module's source file (and reads marshalled bytecode) to inspect a dependency's contents.
Reasoning
The snippet is the standard setuptools pattern for inspecting a module's source or bytecode. Reading a file and compiling it with a path is needed to check a module's contents without importing it. The marshal import matches the bytecode branch of the same function. No network, shell, or payload-decoding behavior is visible.
-
`compile` called on a non-literal expression (ast pass, confidence 0.70)
elif kind == PY_SOURCE:
code = compile(f.read(), path, 'exec')
else:
likely benign
LLM, confidence 0.85
Calls compile() on source read from a module file during dependency inspection.
Reasoning
compile() on file contents read from a path the library itself located is ordinary for a module-introspection utility. The source comes from the local filesystem and nothing is decoded or executed beyond compilation.
-
`__import__` called on a non-literal expression (ast pass, confidence 0.70)
__import__(cython_impl, fromlist=['build_ext']).build_ext except Exception: return False
likely benign
LLM, confidence 0.85
Probes whether the optional Cython build_ext module can be imported, falling back to False on error.
Reasoning
The __import__ call sits inside a try/except that returns False on failure. It is a deliberate availability check for the optional Cython build_ext, using a fixed module name from the library and the comment states the intent. The critical severity reflects the dynamic-import signal, not any malicious behavior.
-
`compile` called on a non-literal expression (ast pass, confidence 0.70)
norm_script = script.replace('\\r\\n', '\\n')
code = compile(norm_script, script_name, 'exec')
exec(code, namespace)
likely benign
LLM, confidence 0.90
Compiles a setup script's source for execution in the launcher namespace.
Reasoning
This is the setuptools launcher that runs a setup script in a supplied namespace, which is its documented purpose. The explicit noqa comment marks the exec as intentional. Script newline normalization is a compatibility step, not obfuscation.
-
`exec` called on a non-literal expression (ast pass, confidence 0.70)
code = compile(norm_script, script_name, 'exec')
exec(code, namespace)
likely benign
LLM, confidence 0.90
Executes the compiled setup script via the launcher, as intended.
Reasoning
Executing a setup script in a controlled namespace is the launcher's job, and the code is annotated as intentional. Nothing in the snippet decodes an obfuscated payload or reaches the network.
Run disclude locally to verify. These commands scan the published file; the "new in this release" marks come from comparing it with the previous release's file, which they don't repeat. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.