vetguard 0.1.0 → 0.2.0

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.
package/README.md CHANGED
@@ -5,10 +5,10 @@ AI-assisted development created: hallucinated (slopsquatted) dependencies,
5
5
  typosquats, and freshly registered malicious packages. No account, no server,
6
6
  no telemetry.
7
7
 
8
- > Early development. `scan` and `check` work today with two detectors live
9
- > (`nonexistent-package`, `young-package`); more detectors, lockfile
10
- > resolution, and a GitHub Action are landing next. Roadmap:
11
- > [docs/PLAN.md](docs/PLAN.md).
8
+ > `vetguard@0.2.0` is on npm, published with provenance. Six detectors,
9
+ > full-tree `package-lock` scanning, diff mode, a config file and baseline for
10
+ > brownfield adoption, and a GitHub Action with text/JSON/SARIF/markdown output.
11
+ > Roadmap to v1.0: [docs/ROADMAP.md](docs/ROADMAP.md).
12
12
 
13
13
  ## Why
14
14
 
@@ -20,29 +20,44 @@ CVE-first tools cannot see it. vetguard targets that gap.
20
20
 
21
21
  ## Install
22
22
 
23
- Not yet published to npm. For now, run from source (see Development). Once
24
- released:
23
+ Published on npm. Run it without installing:
25
24
 
26
25
  ```
27
- npx vetguard scan
26
+ npx vetguard scan # scan the current project
27
+ npx vetguard check <pkg> # vet a package before installing
28
28
  ```
29
29
 
30
+ Or add it to a project with `npm install --save-dev vetguard`. Requires Node.js
31
+ 20 or newer.
32
+
30
33
  ## Usage
31
34
 
32
35
  ```
33
36
  vetguard scan [dir] Scan a project's dependencies (defaults to cwd)
34
37
  vetguard check <pkg> Vet a single package before installing
35
38
  (e.g. vetguard check some-package, foo@1.2.3)
39
+ vetguard diff --base <lockfile> [--head <lockfile>]
40
+ Scan only the dependencies a change introduces
41
+ (head defaults to ./package-lock.json)
42
+ vetguard baseline [dir] Record current findings so later scans fail only on new
43
+ ones (adopt on an existing project, ratchet down later)
36
44
  vetguard --help Show help
37
45
  vetguard --version Show version
38
46
 
39
47
  --offline Do not contact the registry
40
48
  --json Print the report as JSON (for CI and tooling)
41
49
  --sarif Print SARIF 2.1.0 for GitHub code scanning
50
+ --markdown Print compact markdown for a PR comment or summary
51
+ --quiet Print only findings and the verdict
52
+ --no-color Disable ANSI colors (also respects NO_COLOR)
42
53
  --fail-on <severity> Exit non-zero only at or above this severity
43
54
  (critical|high|medium|low|info); default: any finding
44
55
  ```
45
56
 
57
+ Text output is colored by severity only when writing to a terminal; piped or
58
+ redirected output stays plain, and `--no-color` or the `NO_COLOR` environment
59
+ variable turns color off.
60
+
46
61
  `scan` reads the resolved dependency tree from `package-lock.json` (v2 or v3),
47
62
  so it covers transitive dependencies and exact installed versions. Without a
48
63
  supported lockfile it falls back to the manifest's declared dependencies and
@@ -53,6 +68,47 @@ Exit codes: `0` clean or could-not-verify, `1` findings, `2` usage or read
53
68
  error. `check` makes vetguard usable as a pre-install gate, including for
54
69
  coding agents that add dependencies.
55
70
 
71
+ ## Configuration
72
+
73
+ An optional `vetguard.config.json` in the scanned project sets defaults and
74
+ suppresses findings. Command-line flags override it.
75
+
76
+ ```json
77
+ {
78
+ "failOn": "high",
79
+ "offline": false,
80
+ "ignore": [
81
+ {
82
+ "rule": "young-package",
83
+ "package": "our-internal-lib",
84
+ "reason": "first-party package published last week; reviewed"
85
+ }
86
+ ]
87
+ }
88
+ ```
89
+
90
+ Every `ignore` entry requires a `reason`, an ignore without one is a
91
+ configuration error, not a silent skip. A suppressed finding is still shown in
92
+ the report (marked suppressed, with its reason) but does not affect the verdict
93
+ or exit code. The point is an audit trail: you can always see what was waved
94
+ through and why.
95
+
96
+ ### Adopt on an existing project (baseline)
97
+
98
+ A repository that has not been scanned before will usually have some
99
+ pre-existing findings. Rather than fix them all before you can turn vetguard on,
100
+ record a baseline and ratchet down over time:
101
+
102
+ ```
103
+ vetguard baseline # writes .vetguard-baseline.json (commit it)
104
+ ```
105
+
106
+ Later scans report the baselined findings as suppressed and pass; only findings
107
+ **not** in the baseline fail the build. Commit the file so the whole team shares
108
+ the same starting line, then shrink it as you clean things up. A finding's
109
+ identity in the baseline includes its exact version, so a dependency bump is
110
+ re-evaluated rather than grandfathered forever.
111
+
56
112
  ## Use on pull requests
57
113
 
58
114
  vetguard runs in GitHub Actions with no server and no cost: the scan happens on
@@ -67,25 +123,57 @@ on:
67
123
  pull_request:
68
124
  permissions:
69
125
  contents: read
70
- security-events: write
126
+ security-events: write # upload SARIF
127
+ pull-requests: write # only if comment: true
71
128
  jobs:
72
129
  vetguard:
73
130
  runs-on: ubuntu-latest
74
131
  steps:
75
132
  - uses: actions/checkout@v4
76
- - uses: tallyguard/vetguard@v1
133
+ - uses: tallyguard/vetguard@v0.2.0
77
134
  with:
78
135
  fail-on: high # fail the check only on high/critical findings
136
+ comment: true # post/update a single sticky PR comment (optional)
79
137
  - if: always()
80
138
  uses: github/codeql-action/upload-sarif@v3
81
139
  with:
82
140
  sarif_file: vetguard.sarif
83
141
  ```
84
142
 
85
- > The reusable action above resolves once vetguard is published to npm. This
86
- > repository already scans its own pull requests from source via
143
+ `comment: true` posts one sticky comment and updates it in place on later
144
+ pushes, so it never stacks. It needs `pull-requests: write`; leave it off (the
145
+ default) to rely on the SARIF annotations and job summary alone. On pull requests
146
+ from forks the token is read-only, so the comment is skipped without failing.
147
+
148
+ > Pin the action to an exact release (`@v0.2.0`) while vetguard is pre-1.0, since
149
+ > 0.x minor versions may change behaviour; a moving `@v1` tag will follow the
150
+ > 1.0 release. This repository also scans its own pull requests from source via
87
151
  > [.github/workflows/pr-scan.yml](.github/workflows/pr-scan.yml).
88
152
 
153
+ ### Scan only what a pull request changes
154
+
155
+ `diff` mode evaluates just the dependencies a change introduces (new to the head
156
+ lockfile, or a new version), which is the highest-signal moment and keeps the
157
+ report focused. Fetch the base branch's lockfile and diff against the working
158
+ tree:
159
+
160
+ ```yaml
161
+ name: Dependency diff
162
+ on:
163
+ pull_request:
164
+ permissions:
165
+ contents: read
166
+ jobs:
167
+ vetguard:
168
+ runs-on: ubuntu-latest
169
+ steps:
170
+ - uses: actions/checkout@v4
171
+ with:
172
+ fetch-depth: 0 # so the base branch's lockfile is available
173
+ - run: git show "origin/${{ github.base_ref }}:package-lock.json" > /tmp/base-lock.json
174
+ - run: npx vetguard@0.2.0 diff --base /tmp/base-lock.json --fail-on high
175
+ ```
176
+
89
177
  ## What it checks
90
178
 
91
179
  Every finding carries a rule id, severity, and concrete evidence, so a verdict
@@ -121,17 +209,42 @@ scanner can prove a package is free of backdoors, a novel or heavily obfuscated
121
209
  one can evade heuristics, so vetguard raises evidenced signals and reports "no
122
210
  findings", never "safe".
123
211
 
124
- ## Principles
212
+ ## Is vetguard itself safe?
213
+
214
+ A fair question to ask of any security tool, a scanner is exactly what a
215
+ supply-chain attacker would want to disguise malware as. Every claim below is
216
+ verifiable, not asserted:
125
217
 
218
+ - **Provenance-signed releases.** Every version is published from CI with npm
219
+ provenance: cryptographic proof the published bytes were built from this
220
+ public repository's tagged source, not tampered with in between. Verify with
221
+ `npm audit signatures` after install, or the verified badge on the
222
+ [npm page](https://www.npmjs.com/package/vetguard).
223
+ - **Zero runtime dependencies.** vetguard installs nothing but itself, so there
224
+ is no transitive package that could be compromised, and every line that runs
225
+ is code you can read. Verify: `npm view vetguard dependencies` (empty).
226
+ - **No install scripts.** `npm install vetguard` executes no code, there are no
227
+ `preinstall` / `install` / `postinstall` hooks. Verify: read its
228
+ `package.json`.
126
229
  - **Never executes the code it scans.** It reads manifests, lockfiles, and
127
- package metadata as data.
128
- - **Honest verdicts.** When something cannot be verified (offline, private
129
- registry, unsupported lockfile), vetguard reports "could not verify", never
230
+ package metadata as data; it never `require`s, imports, or evals a scanned
231
+ package.
232
+ - **No telemetry, no phone-home.** The only network calls are the registry
233
+ lookups a scan needs, and `--offline` disables even those. Verify: run any
234
+ command with `--offline` and watch it work with no network.
235
+ - **Honest verdicts.** When something cannot be verified (offline, off-registry
236
+ source, unsupported lockfile), vetguard reports "could not verify", never
130
237
  "safe".
131
- - **Near-zero runtime dependencies.** A supply-chain scanner should not ship a
132
- large dependency tree of its own.
133
- - **No telemetry.** The only network calls are the registry lookups a scan
134
- needs, and `--offline` disables even those.
238
+ - **Small, auditable, open source.** The published tarball is a handful of files
239
+ (the bundled CLI, type declarations, `LICENSE`, `README`, `package.json`),
240
+ built from the source in this repository under Apache-2.0.
241
+ - **It scans itself.** On every test run and in CI, vetguard scans its own
242
+ dependencies offline: an introduced name that resembles a popular package (a
243
+ typosquat or slopsquat) is caught with no network and fails the build. The
244
+ pull-request workflow
245
+ ([.github/workflows/pr-scan.yml](.github/workflows/pr-scan.yml)) also runs a
246
+ full live scan for the signals that need the registry. Its own supply chain is
247
+ held to the same bar it applies to yours.
135
248
 
136
249
  ## Development
137
250