Rules / GRN-C003

diffwarnimplemented

GRN-C003 new-import-time-exec

Default severity warn (info in test files)
Kind diff rule: fires only when the trusted version had the property and the new version lost it, or the new version gained a risky property the trusted version lacked.
Status Implemented in 0.1

What it checks

Code that runs when a module is imported gains a call in the sensitive call set. That covers module top-level code and functions it calls, including code reached from __init__.py. Calls are resolved through imports and simple aliasing by reading the source with ast; nothing is executed.

In test files (tests/, test_*.py, conftest.py) it reports at info, unless a non-test module imports the file (directly or through other test modules) or an entry point names it. Test files usually run only with the package's own test suite, which often starts processes or opens sockets at module level. An imported test file runs whenever the package is imported, and one named by an entry point, such as a pytest11 plugin, loads in every pytest run, so those stay at warn.

Why it matters

Top-level module code runs the moment anything imports the package, including your test suite and CI. Libraries rarely start processes, load code or open network connections at import, so a new call like that deserves a look.

Example finding

From the replay of lightning 2.6.2 (MAL-2026-3201). A thread started in lightning/__init__.py launched a credential stealer at import.

lightning 2.6.1 → 2.6.2: WARN
  WARN  GRN-C003 new-import-time-exec: 2.6.2 adds import-time calls to sensitive APIs in 1 module(s)
           - lightning/__init__.py:14 calls subprocess.Popen (in _run_runtime(), reached at import)

The same rule reported lightning 2.6.3 in the replay.

How to resolve it

  1. Read the flagged lines.
  2. Ask whether the release notes explain them. Some libraries legitimately probe the environment at import (for example, checking a GPU driver version with subprocess).
  3. If the call is expected, merge and add an ignore for this version.

Allowlisting

Once you've reviewed a release, ignore this rule for that package and version range. Every ignore needs a reason and an expiry date; after until it stops applying and the report notes that it expired.

[[garnet.ignore]]
package = "examplelib"
versions = "==2.6.2"
rules = ["GRN-C003"]
reason = "probes nvidia-smi at import, see release notes for 2.6.2"
until = "2027-06-30"

To change the rule's severity for every package instead:

[garnet.rules]
"GRN-C003" = "block"   # "off" | "info" | "warn" | "block"

Suppressed findings still appear in JSON and SARIF output, marked with the ignore that matched. The policy format is in SPEC §7; 0.1's garnet diff doesn't read policy files yet.

Sensitive call set

A call is sensitive if it resolves, through imports and simple aliasing and without running any code, to one of these (SPEC §6.3):

The set is versioned with the rule. garnet explain GRN-C003 prints the set your version uses.

See also