Skip to content

Behavioral scanners (setup.py, native binaries, version diff) + severity model docs - #233

Merged
ALLEN-AYODEJI merged 5 commits into
DepRadarOrg:mainfrom
iam-mercy:feature/103-106-behavioral-scanners
Oct 20, 2026
Merged

ALLEN-AYODEJI merged 5 commits into
DepRadarOrg:mainfrom
iam-mercy:feature/103-106-behavioral-scanners

Conversation

@iam-mercy

Copy link
Copy Markdown

Description

Adds the first three behavioral-analysis detectors (src/behavioral/) plus the severity-model documentation they are rated against. Behavioral detectors analyze the contents of an unpacked package, complementing the existing name-based (typosquat) and advisory-based (CVE) checks.

  • [behavioral] Detect suspicious calls in Python setup.py #103 — setup.py suspicious calls (src/behavioral/setup_py.rs): a line-based scan (quote-aware #-comment stripping, no Python AST) flagging subprocess usage (calls and imports), os.system(), exec()/eval(), base64.b64decode() (including direct b64decode imports), and urllib/requests calls — each emitted with its 1-based line number. Command-execution signals rate high, obfuscation/network medium. A normal setuptools setup.py (incl. install_requires=['requests']) scans clean.
  • [behavioral] Flag native binaries shipped inside packages #104 — native binaries (src/behavioral/binaries.rs): scan_binaries walks an unpacked package tree and reports ELF/PE/Mach-O magic headers plus .exe/.dll/.so/.dylib extensions (incl. versioned libfoo.so.1), emitting one low-severity informational finding listing them.
  • [behavioral] Diff two versions of a package for risky changes #105 — version diff (src/behavioral/diff.rs): diff_versions(old, new) reports added/removed files, new install scripts (root setup.py, npm preinstall/install/postinstall), and new suspicious setup.py calls, matched by file and kind so line shifts from a version bump don't create noise.
  • [docs] Document the finding severity model #106 — severity model (docs/severity.md): defines low/medium/high/critical with a rated example per FindingKind and per behavioral signal, the CVSS v3 qualitative mapping, the label fallback, how severity flows into --fail-on/SARIF, and guidance for detector authors. Linked from README and CONTRIBUTING.

Behavioral findings are their own BehavioralFinding type (files inside one package, not lockfile dependencies) but reuse the shared Severity enum, so reports can rank them uniformly. No existing public API or output format changes.

Related Issues

Closes #103
Closes #104
Closes #105
Closes #106

Type of Change

  • New feature (scanner / crawler / contract / client)
  • Documentation
  • Bug fix
  • Breaking change (contract interface, CLI flags, output format)
  • Infrastructure / tooling

Testing Done

All commands run locally against the branch tip (CI parity):

  • cargo fmt --all -- --check — clean
  • cargo clippy --workspace --all-targets --locked -- -D warnings — clean
  • cargo test --workspace --locked — 13 test binaries, 0 failures (20 new behavioral unit tests among them)
  • cargo test -p deprader --features async --locked — passes (CI's second test job)
  • cargo build -p deprader-router --target wasm32v1-none --release --locked — passes (contracts/ untouched; CI wasm job)

New tests:

  • setup_py: clean setuptools file (no findings) + malicious sample flagged at exact line numbers; comment/#-in-string handling; lookalike identifiers (peval, os.system = ...); per-line dedupe; direct b64decode import.
  • binaries: fake headers for each format (ELF, PE, 64-bit LE + 32-bit BE Mach-O); extension matching incl. libfoo.so.1.2.3; mixed nested tempdir tree; informational finding severity/list; clean package.
  • diff: fixture pairs under tests/fixtures/behavioral/ — v1 clean vs v2 malicious sdist (headline case), identical trees, docs-only bump, pre-existing calls not re-reported, new npm postinstall.

Checklist

  • cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings are clean
  • cargo test --workspace --locked passes
  • Contract test snapshots regenerated and committed if contracts/ changed (not applicable — contracts/ untouched)
  • Added an entry to PROGRESS.md (required before the issue can close)
  • README / doc comments updated if user-facing behavior changed (docs/severity.md linked from README and CONTRIBUTING)

PyPI sdists execute setup.py at install time, making it the direct analogue of npm install scripts. Adds the behavioral analysis module and its first detector: a line-based scan (no Python AST) that strips # comments, then flags subprocess usage (calls and imports), os.system(), exec()/eval(), base64.b64decode() (including direct b64decode imports), and urllib/requests calls. Each hit is a BehavioralFinding carrying the 1-based line number; command-execution signals rate high and obfuscation/network calls rate medium per docs/severity.md. Dependency names such as install_requires=["requests"] are not calls and do not trigger.

Closes DepRadarOrg#103
Prebuilt executables in an npm or PyPI package cannot be code-reviewed the way source can, and dropped binaries are a common payload carrier. scan_binaries walks an unpacked package tree and reports every file carrying an ELF, PE or Mach-O magic header, or with a native extension (.exe, .dll, .so, .dylib, including versioned libfoo.so.1). Magic bytes are sniffed before extensions are consulted, so an extension-less ELF is still caught. Emits one low-severity informational finding listing all binaries - a review prompt, not a red flag, since real projects ship legitimate native addons.

Closes DepRadarOrg#104
The most useful supply-chain signal is often what changed: a patch release that adds an install script or network code. diff_versions(old, new) compares two unpacked package trees and reports added/removed files, install scripts present in new but not old (a root setup.py, or npm preinstall/install/postinstall entries in package.json), and suspicious setup.py calls new in new. Calls are matched by file and kind rather than line, so ordinary line shifts from a version bump create no noise. PackageDiff::is_clean() is true when only benign files changed.

Closes DepRadarOrg#105
Contributors adding detectors need one place that defines what low, medium, high and critical mean in DepRadar. Adds docs/severity.md: a definition per level, a rated example per FindingKind (homoglyph typosquat -> critical, distance typosquat -> high, vulnerability -> its advisory level, unrated advisory -> high) and per behavioral signal (setup.py command execution -> high, obfuscation/network -> medium, native binaries -> low, new install script between versions -> medium), the CVSS v3 qualitative mapping (0.0-3.9 low, 4.0-6.9 medium, 7.0-8.9 high, 9.0-10.0 critical) with the label fallback, how severity flows into --fail-on, SARIF levels and security-severity, and guidance for detector authors. Linked from README and CONTRIBUTING; all commands and links verified.

Closes DepRadarOrg#106
@drips-wave

drips-wave Bot commented Oct 19, 2026

Copy link
Copy Markdown

@iam-mercy Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@ALLEN-AYODEJI
ALLEN-AYODEJI merged commit cc87c10 into DepRadarOrg:main Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants