pydepgate scan
Scan a Python package or file for supply-chain malware patterns in startup vectors.
pydepgate scan [flags] <target>
pydepgate scan [flags] --single <path> [--as <kind>]
Target dispatch
The positional <target> argument accepts three forms:
Wheel or sdist path: a path to a .whl or .tar.gz file on disk.
pydepgate scan some-package-1.0.0-py3-none-any.whl
pydepgate scan some-package-1.0.0.tar.gz
Installed package name: the name of a package currently installed in the active Python environment, resolved via importlib.metadata.
pydepgate scan litellm
pydepgate scan requests
Single file (via --single): a single loose file, bypassing all wheel/sdist/package dispatch. See Single file mode below.
Scan-specific flags
--single <path>
Analyze a single file directly instead of dispatching through the wheel, sdist, or installed-package path. The file kind is inferred from the filename. See Single file mode for full details.
Cannot be combined with a positional <target>.
--as <kind>
Override the inferred file kind when using --single. Only valid with --single.
Valid kinds:
| Kind | Description |
|---|---|
setup_py | setup.py context. Most permissive: density rules promote to HIGH/CRITICAL. |
init_py | __init__.py context |
pth | .pth startup file |
sitecustomize | sitecustomize.py context |
usercustomize | usercustomize.py context |
library_py | Ordinary library file. Used for deep-mode calibration. Density analyzer only. |
--deep
Also analyze ordinary library .py files in the artifact, not just startup vectors. Only the density analyzer runs on library files; the other analyzers would produce unacceptable false-positive rates outside startup-vector context.
Files in excluded directories (tests/, docs/, and similar) are still skipped regardless of --deep.
Cannot be combined with --single.
--no-bar
Suppress the per-file progress bar during artifact scans. The bar is automatically suppressed when stderr is not a TTY (piped output, CI runs, redirected logs), so this flag is mainly for interactive terminals where you want clean output. No effect in --single mode.
Single file mode
--single bypasses dispatch and runs the analyzer directly on one file. File kind is inferred from the filename by these rules:
- Files named
setup.pyare classified assetup_py. - Files named
__init__.pyare classified asinit_py. - Files named
sitecustomize.pyare classified assitecustomize. - Files named
usercustomize.pyare classified asusercustomize. - Files with a
.pthextension are classified aspth. - Any other
.pyfile defaults tosetup_py(the most permissive context, which surfaces every signal at realistic attack-shape severity).
Override with --as when the inferred kind is wrong:
# Analyze as __init__.py context even though the filename is ambiguous
pydepgate scan --single payload.py --as init_py
# Analyze with library rules to test density signals specifically
pydepgate scan --single generated_parser.py --as library_py
setup_py is the recommended --as value when iterating on new signals or test fixtures, because it enables the highest severity promotions and produces the most complete signal output.
Global flags
All global flags apply to scan. The most commonly used ones are summarized here.
--format
pydepgate scan --format json package.whl
pydepgate scan --format sarif package.whl > results.sarif
human (default) renders ANSI-formatted output to stdout with the finding-distribution map. json emits a structured JSON document. sarif emits a SARIF 2.1.0 document. See Output Formats for schema details and SARIF Integration for GitHub Code Scanning ingestion.
--min-severity
pydepgate scan --min-severity high package.whl
Suppress findings below this severity in output and in the exit code computation. Accepted values: info, low, medium, high, critical.
--ci
pydepgate scan --ci package.whl
CI mode. If --format is not explicitly set, it is forced to json. If --color is currently auto, it is forced to never. CI mode does not change --min-severity. Combine with --min-severity high when you want to block only on HIGH and CRITICAL findings in CI:
pydepgate scan --ci --min-severity high package.whl
--strict-exit
When set, the exit code is computed from all findings regardless of --min-severity. Useful when you want filtered display (showing only HIGH and above) but want the exit code to reflect the full finding set.
# Display only HIGH+, but exit 2 if any finding exists at any severity
pydepgate scan --min-severity high --strict-exit package.whl
--rules-file
pydepgate scan --rules-file ./company-rules.gate package.whl
Load a custom rules file. Auto-discovery checks ./pydepgate.gate then ~/.config/pydepgate/pydepgate.gate when this flag is not set. See Custom Rules.
--peek and decode flags
pydepgate scan --peek --decode-payload-depth 4 package.whl
--peek enables the payload-peek enricher. --decode-payload-depth N enables the recursive decode pipeline. See the full global flags table for all decode-related flags and Decode Payloads for a walkthrough.
--sarif-srcroot
pydepgate scan --format sarif --sarif-srcroot /path/to/repo package.whl
Populate originalUriBaseIds.PROJECTROOT in SARIF output. Required for correct path resolution in GitHub Code Scanning. Only meaningful with --format sarif. See SARIF Integration.
Exit codes
| Code | Meaning |
|---|---|
0 | Clean. No findings at or above --min-severity. |
1 | Findings present, none HIGH or CRITICAL. |
2 | At least one HIGH or CRITICAL finding. |
3 | Tool error. Scan could not complete. |
These are stable as of v0.1. See Exit Codes.
Examples
Scan a wheel with default settings:
pydepgate scan package-1.0.0-py3-none-any.whl
Scan a wheel in CI, fail on HIGH or CRITICAL:
pydepgate scan --ci --min-severity high package-1.0.0-py3-none-any.whl
Scan and emit JSON for downstream processing:
pydepgate scan --format json package.whl > results.json
Scan with payload decoding and IOC archive output:
pydepgate scan \
--peek \
--decode-payload-depth 4 \
--decode-iocs full \
--decode-location ./iocs \
package.whl
Scan a single file and see all signals:
pydepgate scan --single suspicious.py
Scan a single file and force a specific analysis context:
pydepgate scan --single ambiguous.py --as setup_py
Scan an installed package:
pydepgate scan litellm
Emit SARIF for GitHub Code Scanning:
pydepgate scan \
--format sarif \
--sarif-srcroot "$PWD" \
--peek \
--decode-payload-depth 4 \
package.whl > pydepgate.sarif