vetguard 0.0.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 +132 -19
- package/dist/{chunk-XXICU3EZ.js → chunk-2DIOTV5P.js} +414 -50
- package/dist/cli.js +100 -16
- package/dist/index.d.ts +138 -12
- package/dist/index.js +33 -3
- package/package.json +2 -2
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
|
-
>
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
> [docs/
|
|
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
|
-
|
|
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@
|
|
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
|
-
|
|
86
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
129
|
-
|
|
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
|
-
- **
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
|