depenemy 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. depenemy-0.1.0/.depenemy.yml +43 -0
  2. depenemy-0.1.0/.github/workflows/ci.yml +75 -0
  3. depenemy-0.1.0/.github/workflows/publish.yml +30 -0
  4. depenemy-0.1.0/.gitignore +58 -0
  5. depenemy-0.1.0/.pre-commit-config.yaml +11 -0
  6. depenemy-0.1.0/CHANGELOG.md +26 -0
  7. depenemy-0.1.0/LICENSE +21 -0
  8. depenemy-0.1.0/PKG-INFO +268 -0
  9. depenemy-0.1.0/README.md +210 -0
  10. depenemy-0.1.0/action.yml +82 -0
  11. depenemy-0.1.0/assets/logos/logo.svg +26 -0
  12. depenemy-0.1.0/depenemy/__init__.py +4 -0
  13. depenemy-0.1.0/depenemy/__main__.py +3 -0
  14. depenemy-0.1.0/depenemy/advisories/__init__.py +5 -0
  15. depenemy-0.1.0/depenemy/advisories/osv.py +184 -0
  16. depenemy-0.1.0/depenemy/cache.py +57 -0
  17. depenemy-0.1.0/depenemy/cli.py +187 -0
  18. depenemy-0.1.0/depenemy/config.py +152 -0
  19. depenemy-0.1.0/depenemy/data/top_npm_packages.json +15 -0
  20. depenemy-0.1.0/depenemy/data/top_pypi_packages.json +14 -0
  21. depenemy-0.1.0/depenemy/fetchers/__init__.py +8 -0
  22. depenemy-0.1.0/depenemy/fetchers/base.py +27 -0
  23. depenemy-0.1.0/depenemy/fetchers/crates.py +97 -0
  24. depenemy-0.1.0/depenemy/fetchers/github.py +126 -0
  25. depenemy-0.1.0/depenemy/fetchers/npm.py +176 -0
  26. depenemy-0.1.0/depenemy/fetchers/pypi.py +158 -0
  27. depenemy-0.1.0/depenemy/parsers/__init__.py +7 -0
  28. depenemy-0.1.0/depenemy/parsers/base.py +35 -0
  29. depenemy-0.1.0/depenemy/parsers/npm.py +98 -0
  30. depenemy-0.1.0/depenemy/parsers/python.py +153 -0
  31. depenemy-0.1.0/depenemy/parsers/rust.py +69 -0
  32. depenemy-0.1.0/depenemy/reporters/__init__.py +7 -0
  33. depenemy-0.1.0/depenemy/reporters/json_reporter.py +43 -0
  34. depenemy-0.1.0/depenemy/reporters/sarif.py +91 -0
  35. depenemy-0.1.0/depenemy/reporters/table.py +146 -0
  36. depenemy-0.1.0/depenemy/rules/__init__.py +44 -0
  37. depenemy-0.1.0/depenemy/rules/base.py +65 -0
  38. depenemy-0.1.0/depenemy/rules/behavioral/__init__.py +5 -0
  39. depenemy-0.1.0/depenemy/rules/behavioral/b001_range_specifier.py +45 -0
  40. depenemy-0.1.0/depenemy/rules/behavioral/b002_unpinned.py +33 -0
  41. depenemy-0.1.0/depenemy/rules/behavioral/b003_lagging_version.py +59 -0
  42. depenemy-0.1.0/depenemy/rules/reputation/__init__.py +21 -0
  43. depenemy-0.1.0/depenemy/rules/reputation/r001_young_author.py +49 -0
  44. depenemy-0.1.0/depenemy/rules/reputation/r002_young_package.py +49 -0
  45. depenemy-0.1.0/depenemy/rules/reputation/r003_low_weekly_downloads.py +38 -0
  46. depenemy-0.1.0/depenemy/rules/reputation/r004_low_total_downloads.py +38 -0
  47. depenemy-0.1.0/depenemy/rules/reputation/r005_stale_package.py +50 -0
  48. depenemy-0.1.0/depenemy/rules/reputation/r006_few_contributors.py +41 -0
  49. depenemy-0.1.0/depenemy/rules/reputation/r007_below_security_patch.py +48 -0
  50. depenemy-0.1.0/depenemy/rules/reputation/r008_deprecated.py +33 -0
  51. depenemy-0.1.0/depenemy/rules/reputation/r009_typosquatting.py +82 -0
  52. depenemy-0.1.0/depenemy/rules/supply_chain/__init__.py +13 -0
  53. depenemy-0.1.0/depenemy/rules/supply_chain/s001_install_scripts.py +36 -0
  54. depenemy-0.1.0/depenemy/rules/supply_chain/s002_no_source_repo.py +35 -0
  55. depenemy-0.1.0/depenemy/rules/supply_chain/s003_archived_repo.py +35 -0
  56. depenemy-0.1.0/depenemy/rules/supply_chain/s004_dependency_confusion.py +73 -0
  57. depenemy-0.1.0/depenemy/rules/supply_chain/s005_malicious_package.py +36 -0
  58. depenemy-0.1.0/depenemy/scanner.py +152 -0
  59. depenemy-0.1.0/depenemy/types.py +114 -0
  60. depenemy-0.1.0/pyproject.toml +80 -0
  61. depenemy-0.1.0/tests/__init__.py +0 -0
  62. depenemy-0.1.0/tests/conftest.py +83 -0
  63. depenemy-0.1.0/tests/fixtures/npm/b001_caret_ranges.json +14 -0
  64. depenemy-0.1.0/tests/fixtures/npm/b001_gte_range.json +12 -0
  65. depenemy-0.1.0/tests/fixtures/npm/b001_latest_tag.json +13 -0
  66. depenemy-0.1.0/tests/fixtures/npm/b001_or_range.json +11 -0
  67. depenemy-0.1.0/tests/fixtures/npm/b001_star_wildcard.json +13 -0
  68. depenemy-0.1.0/tests/fixtures/npm/b001_tilde_ranges.json +13 -0
  69. depenemy-0.1.0/tests/fixtures/npm/b001_x_range.json +14 -0
  70. depenemy-0.1.0/tests/fixtures/npm/b002_empty_version.json +10 -0
  71. depenemy-0.1.0/tests/fixtures/npm/b002_x_version.json +10 -0
  72. depenemy-0.1.0/tests/fixtures/npm/clean_exact_pins.json +15 -0
  73. depenemy-0.1.0/tests/fixtures/npm/future_file_dep.json +12 -0
  74. depenemy-0.1.0/tests/fixtures/npm/future_git_dep.json +13 -0
  75. depenemy-0.1.0/tests/fixtures/npm/future_http_dep.json +10 -0
  76. depenemy-0.1.0/tests/fixtures/npm/future_install_scripts.json +14 -0
  77. depenemy-0.1.0/tests/fixtures/npm/future_no_license.json +9 -0
  78. depenemy-0.1.0/tests/fixtures/npm/mixed_bad_patterns.json +23 -0
  79. depenemy-0.1.0/tests/test_parsers/__init__.py +0 -0
  80. depenemy-0.1.0/tests/test_parsers/test_npm.py +67 -0
  81. depenemy-0.1.0/tests/test_parsers/test_npm_parser.py +134 -0
  82. depenemy-0.1.0/tests/test_parsers/test_python.py +57 -0
  83. depenemy-0.1.0/tests/test_reporters/__init__.py +0 -0
  84. depenemy-0.1.0/tests/test_reporters/test_json_reporter.py +125 -0
  85. depenemy-0.1.0/tests/test_reporters/test_sarif.py +70 -0
  86. depenemy-0.1.0/tests/test_reporters/test_table.py +189 -0
  87. depenemy-0.1.0/tests/test_rules/__init__.py +0 -0
  88. depenemy-0.1.0/tests/test_rules/test_b001_range_specifier.py +128 -0
  89. depenemy-0.1.0/tests/test_rules/test_b002_unpinned.py +95 -0
  90. depenemy-0.1.0/tests/test_rules/test_behavioral.py +92 -0
  91. depenemy-0.1.0/tests/test_rules/test_detection_coverage.py +276 -0
  92. depenemy-0.1.0/tests/test_rules/test_r009_typosquatting.py +106 -0
  93. depenemy-0.1.0/tests/test_rules/test_reputation.py +160 -0
  94. depenemy-0.1.0/tests/test_rules/test_s004_s005.py +227 -0
  95. depenemy-0.1.0/tests/test_rules/test_supply_chain.py +55 -0
  96. depenemy-0.1.0/tests/test_scanner.py +98 -0
@@ -0,0 +1,43 @@
1
+ # depenemy configuration
2
+ # All thresholds are configurable. Set a rule to false to disable it.
3
+
4
+ thresholds:
5
+ min_weekly_downloads: 1000
6
+ min_total_downloads: 10000
7
+ min_author_account_age_days: 365
8
+ min_package_age_days: 180
9
+ max_stale_days: 730
10
+ min_contributors: 5
11
+ max_version_lag: 10 # how many minor versions behind is too old
12
+ typosquatting_distance: 1 # max edit distance to flag as typosquatting
13
+
14
+ rules:
15
+ B001: warning # range specifier (^, ~, >=, *) - hygiene
16
+ B002: error # no version pinned - active risk
17
+ B003: warning # lagging version - hygiene, CVEs caught by R007
18
+ R001: warning # young author account - signal, not proof
19
+ R002: warning # young package - signal, not proof
20
+ R003: warning # low weekly downloads - signal
21
+ R004: warning # low total downloads - signal
22
+ R005: warning # stale package - maintenance issue, not active threat
23
+ R006: warning # few contributors - signal
24
+ R007: error # target version below known security patch - active threat
25
+ R008: warning # deprecated - should migrate, not urgent
26
+ R009: warning # typosquatting suspected - signal
27
+ S001: error # install scripts present - executes code on install
28
+ S002: warning # no source repository linked - hygiene
29
+ S003: warning # source repository archived - maintenance issue
30
+ S004: warning # dependency confusion - signal
31
+ S005: error # known malicious package history in OSV - active threat
32
+
33
+ # Packages to ignore (with reason)
34
+ ignore: []
35
+ # ignore:
36
+ # - name: my-internal-package
37
+ # ecosystem: npm
38
+ # reason: "internal fork, not on public registry"
39
+
40
+ # Ecosystems to scan (default: all detected)
41
+ # ecosystems:
42
+ # - npm
43
+ # - pypi
@@ -0,0 +1,75 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test (Python ${{ matrix.python-version }})
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ python-version: ["3.11", "3.12"]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python ${{ matrix.python-version }}
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+
25
+ - name: Install dependencies
26
+ run: |
27
+ pip install -e ".[dev]"
28
+
29
+ - name: Lint with ruff
30
+ run: ruff check .
31
+
32
+ - name: Type check with mypy
33
+ run: mypy depenemy
34
+
35
+ - name: Run tests
36
+ run: pytest --cov=depenemy --cov-report=xml
37
+
38
+ - name: Upload coverage
39
+ uses: codecov/codecov-action@v4
40
+ if: matrix.python-version == '3.11'
41
+ with:
42
+ file: ./coverage.xml
43
+
44
+ self-scan:
45
+ name: Self-scan (depenemy scans itself)
46
+ runs-on: ubuntu-latest
47
+ needs: test
48
+ permissions:
49
+ contents: read
50
+ security-events: write
51
+
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+
55
+ - name: Set up Python
56
+ uses: actions/setup-python@v5
57
+ with:
58
+ python-version: "3.11"
59
+
60
+ - name: Install depenemy
61
+ run: pip install -e .
62
+
63
+ - name: Run depenemy on this repo
64
+ env:
65
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
66
+ run: |
67
+ depenemy scan . --output sarif --output-file depenemy.sarif --fail-on error || true
68
+
69
+ - name: Upload SARIF
70
+ uses: github/codeql-action/upload-sarif@v4
71
+ if: always()
72
+ continue-on-error: true
73
+ with:
74
+ sarif_file: depenemy.sarif
75
+ category: depenemy-self-scan
@@ -0,0 +1,30 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ name: Publish to PyPI
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ id-token: write # Required for trusted publishing
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.11"
22
+
23
+ - name: Install build tools
24
+ run: pip install hatchling build
25
+
26
+ - name: Build package
27
+ run: python -m build
28
+
29
+ - name: Publish to PyPI
30
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,58 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ dist/
9
+ eggs/
10
+ .eggs/
11
+ lib/
12
+ lib64/
13
+ parts/
14
+ sdist/
15
+ var/
16
+ wheels/
17
+ *.egg-info/
18
+ .installed.cfg
19
+ *.egg
20
+ MANIFEST
21
+ .venv/
22
+ venv/
23
+ ENV/
24
+ env/
25
+
26
+ # Testing
27
+ .tox/
28
+ .nox/
29
+ .coverage
30
+ .coverage.*
31
+ coverage.xml
32
+ htmlcov/
33
+ .pytest_cache/
34
+ .mypy_cache/
35
+
36
+ # IDEs
37
+ .idea/
38
+ .vscode/
39
+ *.swp
40
+ *.swo
41
+
42
+ # OS
43
+ .DS_Store
44
+ Thumbs.db
45
+
46
+ # depenemy output
47
+ .depenemy_cache/
48
+ depenemy-results.json
49
+
50
+ # local demo
51
+ demo/
52
+
53
+ # Team coordination
54
+ TODO.md
55
+
56
+ # Secrets
57
+ .env
58
+ *.key
@@ -0,0 +1,11 @@
1
+ repos:
2
+ - repo: https://github.com/W3OSC/depenemy
3
+ rev: v0.1.0
4
+ hooks:
5
+ - id: depenemy
6
+ name: depenemy dependency scan
7
+ language: python
8
+ entry: depenemy scan
9
+ args: [--fail-on, error]
10
+ pass_filenames: false
11
+ always_run: true
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-04-09
11
+
12
+ ### Added
13
+ - Initial release
14
+ - npm and PyPI ecosystem support
15
+ - Behavioral checks: range specifiers, unpinned versions, lagging versions
16
+ - Reputation checks: author age, package age, download counts, contributors, staleness, known CVEs, deprecated packages, typosquatting
17
+ - Supply chain checks: install scripts, missing source repo, archived repo, dependency confusion, known malicious packages
18
+ - Deprecated package detection
19
+ - OSV.dev integration for security advisories
20
+ - SARIF 2.1.0 output (GitHub Code Scanning compatible)
21
+ - Rich terminal table output
22
+ - JSON output
23
+ - Disk-backed caching
24
+ - GitHub Action support
25
+ - Pre-commit hook support
26
+ - Configurable thresholds via `.depenemy.yml`
depenemy-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 W3OSC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,268 @@
1
+ Metadata-Version: 2.4
2
+ Name: depenemy
3
+ Version: 0.1.0
4
+ Summary: Dependency scanner that finds your enemies in the supply chain
5
+ Project-URL: Homepage, https://github.com/W3OSC/depenemy
6
+ Project-URL: Repository, https://github.com/W3OSC/depenemy
7
+ Project-URL: Issues, https://github.com/W3OSC/depenemy/issues
8
+ Project-URL: Changelog, https://github.com/W3OSC/depenemy/blob/main/CHANGELOG.md
9
+ Author-email: W3OSC <contact@w3osc.com>
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 W3OSC
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: dependencies,sarif,sbom,scanner,security,supply-chain
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Environment :: Console
35
+ Classifier: Intended Audience :: Developers
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3.11
39
+ Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Topic :: Security
41
+ Classifier: Topic :: Software Development :: Quality Assurance
42
+ Requires-Python: >=3.9
43
+ Requires-Dist: anyio>=4.4.0
44
+ Requires-Dist: httpx>=0.27.0
45
+ Requires-Dist: pyyaml>=6.0
46
+ Requires-Dist: rich>=13.7.0
47
+ Requires-Dist: tomli>=2.0.0; python_version < '3.11'
48
+ Requires-Dist: typer>=0.12.0
49
+ Provides-Extra: dev
50
+ Requires-Dist: mypy>=1.10.0; extra == 'dev'
51
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
52
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
53
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
54
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
55
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
56
+ Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
57
+ Description-Content-Type: text/markdown
58
+
59
+ <div align="center">
60
+
61
+ <img src="assets/logos/logo.svg" alt="depenemy" width="380"/>
62
+
63
+ **Your dependencies could be your enemy.**
64
+
65
+ Depenemy scans your project for supply chain risks, behavioral issues, and reputation red flags - before they can do damage.
66
+
67
+ [![CI](https://github.com/W3OSC/depenemy/actions/workflows/ci.yml/badge.svg)](https://github.com/W3OSC/depenemy/actions/workflows/ci.yml)
68
+ [![PyPI](https://img.shields.io/pypi/v/depenemy)](https://pypi.org/project/depenemy/)
69
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)
70
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
71
+
72
+ </div>
73
+
74
+ ---
75
+
76
+ ## Why depenemy?
77
+
78
+ Modern projects pull in hundreds of dependencies. Each one is a potential entry point for a supply chain attack - a compromised maintainer account, a typosquatted package, an old version with a known CVE, or a package that runs arbitrary code on install.
79
+
80
+ Depenemy gives you **a single command** that audits all your dependencies across npm, Python, Rust, and Solidity - and tells you exactly what looks suspicious and why.
81
+
82
+ ---
83
+
84
+ ## What it detects
85
+
86
+ ### Behavioral risks
87
+
88
+ | ID | Name | Description | Severity |
89
+ |----|------|-------------|----------|
90
+ | B001 | Range specifier | Version uses `^`, `~`, `>=`, `*` - allows unexpected updates | Warning |
91
+ | B002 | No version pinned | No version specified at all | Error |
92
+ | B003 | Lagging version | Pinned version is significantly behind latest | Warning |
93
+
94
+ ### Reputation signals
95
+
96
+ | ID | Name | Description | Severity |
97
+ |----|------|-------------|----------|
98
+ | R001 | Young author account | Package author's GitHub account is < 12 months old | Warning |
99
+ | R002 | New package | Package was first published < 6 months ago | Warning |
100
+ | R003 | Low weekly downloads | < 1,000 weekly downloads | Warning |
101
+ | R004 | Low total downloads | < 10,000 total downloads | Warning |
102
+ | R005 | No updates in 2+ years | Last publish was over 2 years ago | Warning |
103
+ | R006 | Few contributors | Fewer than 5 contributors on GitHub | Warning |
104
+ | R007 | Known vulnerable version | Your version is below a known security patch (OSV/CVE) | Error |
105
+ | R008 | Deprecated package | Package is officially marked as deprecated | Warning |
106
+ | R009 | Typosquatting suspected | Name is suspiciously close to a popular package | Warning |
107
+
108
+ ### Supply chain risks
109
+
110
+ | ID | Name | Description | Severity |
111
+ |----|------|-------------|----------|
112
+ | S001 | Install scripts | Package runs code at install time (`postinstall`, `preinstall`) | Error |
113
+ | S002 | No source repository | No GitHub/GitLab link in package metadata | Warning |
114
+ | S003 | Archived repository | Source repo has been archived or deleted | Warning |
115
+ | S004 | Dependency confusion | Private package name found on public registry | Warning |
116
+ | S005 | Known malicious package | Package has a recorded history of malicious activity (OSV) | Error |
117
+
118
+ ---
119
+
120
+ ## Supported ecosystems
121
+
122
+ | Ecosystem | Manifest files |
123
+ |-----------|----------------|
124
+ | **npm / Node.js** | `package.json`, `package-lock.json`, `yarn.lock` |
125
+ | **Python** | `requirements*.txt`, `pyproject.toml`, `Pipfile` |
126
+ | **Rust** | `Cargo.toml` |
127
+ | **Solidity** | Foundry / Hardhat (delegates to npm) |
128
+
129
+ ---
130
+
131
+ ## Installation
132
+
133
+ ```bash
134
+ pip install depenemy
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Usage
140
+
141
+ ### CLI
142
+
143
+ ```bash
144
+ # Scan your project
145
+ depenemy scan .
146
+
147
+ # Scan a specific file
148
+ depenemy scan pyproject.toml
149
+
150
+ # Output as SARIF (for GitHub Code Scanning)
151
+ depenemy scan . --output sarif --output-file results.sarif
152
+
153
+ # Output as JSON to a custom filename (table scan always writes depenemy-results.json automatically)
154
+ depenemy scan . --output json --output-file my-results.json
155
+
156
+ # Pipe JSON output to another tool
157
+ depenemy scan . --output json | jq '.findings'
158
+
159
+ # Fail the command if any warnings exist (useful in CI)
160
+ depenemy scan . --fail-on warning
161
+
162
+ # List all available rules
163
+ depenemy rules
164
+ ```
165
+
166
+ **Example output:**
167
+ <img width="1070" height="711" alt="image" src="https://github.com/user-attachments/assets/96d22774-9649-4b2e-ba09-c3311df8ae3c" />
168
+
169
+
170
+ ---
171
+
172
+ ### GitHub Action
173
+
174
+ Add to your workflow and results appear automatically as [Code Scanning alerts](https://docs.github.com/en/code-security/code-scanning) on every pull request:
175
+
176
+ ```yaml
177
+ - name: Scan dependencies
178
+ uses: W3OSC/depenemy@v0.1.0
179
+ with:
180
+ token: ${{ secrets.GITHUB_TOKEN }}
181
+ fail-on: error
182
+ ```
183
+
184
+ ---
185
+
186
+ ### Pre-commit hook
187
+
188
+ Block pushes that introduce risky dependencies. Add to `.pre-commit-config.yaml`:
189
+
190
+ ```yaml
191
+ repos:
192
+ - repo: https://github.com/W3OSC/depenemy
193
+ rev: v0.1.0
194
+ hooks:
195
+ - id: depenemy
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Configuration
201
+
202
+ Create `.depenemy.yml` in your repository root to customize thresholds, severities, and ignore specific packages:
203
+
204
+ ```yaml
205
+ thresholds:
206
+ min_weekly_downloads: 1000 # R003 threshold
207
+ min_total_downloads: 10000 # R004 threshold
208
+ min_author_account_age_days: 365 # R001 threshold
209
+ min_package_age_days: 180 # R002 threshold
210
+ max_stale_days: 730 # R005 threshold
211
+ min_contributors: 5 # R006 threshold
212
+ max_version_lag: 10 # B003 threshold (minor versions)
213
+ typosquatting_distance: 1 # R009 threshold (edit distance)
214
+
215
+ rules:
216
+ B001: warning # downgrade range specifier to warning
217
+ R003: false # disable low downloads check entirely
218
+
219
+ ignore:
220
+ - name: my-internal-package
221
+ ecosystem: npm
222
+ reason: "Internal fork, not on public registry"
223
+ - name: legacy-tool
224
+ ecosystem: pypi
225
+ reason: "Approved exception, tracked in JIRA-1234"
226
+ ```
227
+
228
+ Set a rule to `false` to disable it entirely. All other rules accept `warning` or `error`.
229
+
230
+ ---
231
+
232
+ ## Output formats
233
+
234
+ | Format | Flag | Best for |
235
+ |--------|------|----------|
236
+ | Table (default) | `--output table` | Terminal / CI logs |
237
+ | SARIF | `--output sarif` | GitHub Code Scanning |
238
+ | JSON | `--output json` | Custom integrations, dashboards |
239
+
240
+ ---
241
+
242
+ ## How it works
243
+
244
+ <img width="619" height="813" alt="image" src="https://github.com/user-attachments/assets/07a028e4-5c1f-402e-804e-c9e63148d0aa" />
245
+
246
+ API responses are cached for **6 hours** in `.depenemy_cache/` to avoid rate limits on repeated runs. Use `--no-cache` to force fresh data.
247
+
248
+ ---
249
+
250
+ ## GitHub Token
251
+
252
+ A GitHub token unlocks author account age (R001) and contributor count (R006) checks. Without it, those rules are skipped.
253
+
254
+ ```bash
255
+ # CLI
256
+ depenemy scan . --github-token ghp_xxxx
257
+
258
+ # Or via environment variable
259
+ GITHUB_TOKEN=ghp_xxxx depenemy scan .
260
+ ```
261
+
262
+ In GitHub Actions, `${{ secrets.GITHUB_TOKEN }}` is available automatically.
263
+
264
+ ---
265
+
266
+ ## License
267
+
268
+ MIT - see [LICENSE](LICENSE)