@aldegad/safedeps 2.1.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/ARCHITECTURE.md +595 -0
- package/LICENSE +190 -0
- package/README.md +311 -0
- package/ROADMAP.md +131 -0
- package/SKILL.md +200 -0
- package/agents/openai.yaml +4 -0
- package/bin/safedeps +842 -0
- package/lib/ledger/ledger.sh +346 -0
- package/lib/providers/providers.sh +479 -0
- package/package.json +41 -0
- package/scripts/install/install-safedeps-hooks.mjs +209 -0
- package/scripts/install/install-safedeps-recheck-agent.mjs +203 -0
- package/scripts/install/migrate-safedeps-state.mjs +91 -0
- package/scripts/safedeps-post-verify.sh +584 -0
- package/scripts/safedeps-pre-guard.sh +427 -0
- package/scripts/safedeps-recheck-alert.sh +115 -0
- package/scripts/test/e2e.sh +107 -0
- package/scripts/test/fixture-provider.mjs +104 -0
- package/scripts/test/smoke.sh +89 -0
package/SKILL.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: safedeps
|
|
3
|
+
description: Gate dependency installs (npm/pip/cargo/go/gem/maven/nuget) with OSV-backed advisory checks, approved-spec ledger, and post-install reorg rollback. Run `safedeps check <eco> <pkg>@<range>` before any install command.
|
|
4
|
+
hooks:
|
|
5
|
+
- type: PreToolUse
|
|
6
|
+
script: scripts/safedeps-pre-guard.sh
|
|
7
|
+
- type: PostToolUse
|
|
8
|
+
script: scripts/safedeps-post-verify.sh
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Safedeps
|
|
12
|
+
|
|
13
|
+
Safedeps protects development dependency installs with a three-phase flow:
|
|
14
|
+
|
|
15
|
+
1. **Phase 1 — Advisory gate (`safedeps check`)**: query OSV (canonical advisory truth), CISA KEV (overlay), and GitHub Advisory (enrichment) before install. Write the approved (ecosystem, package, version) tuple to `~/.safedeps/approved-specs/<hash>.json` with a 30-day TTL.
|
|
16
|
+
2. **Phase 2 — Hook enforcement (`scripts/safedeps-pre-guard.sh`)**: the PreToolUse hook does not call providers. It only checks the approved-spec ledger for the package/version in the about-to-run install command. Miss or expired → block with a structured message that names the exact `safedeps check` command to run next.
|
|
17
|
+
3. **Phase 3 — Post-install reorg (`scripts/safedeps-post-verify.sh`)**: v1 reorg engine rolls back when the lockfile diverges from the approved spec or install scripts look suspicious.
|
|
18
|
+
|
|
19
|
+
## CLI Reference
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
safedeps check <ecosystem> <pkg>@<version|range> [--json]
|
|
23
|
+
safedeps ledger [--json]
|
|
24
|
+
safedeps revoke <hash> | <ecosystem> <pkg>@<version> | <pkg>@<version> [--reason <r>] [--json]
|
|
25
|
+
safedeps re-check [--json]
|
|
26
|
+
safedeps migrate [--keep-legacy]
|
|
27
|
+
safedeps help [command]
|
|
28
|
+
safedeps version
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Ecosystems** (OSV-normalized): `npm`, `pypi`, `crates.io`, `go`, `rubygems`, `maven`, `nuget`.
|
|
32
|
+
|
|
33
|
+
**Exit codes**:
|
|
34
|
+
|
|
35
|
+
| Code | Meaning |
|
|
36
|
+
|---:|---|
|
|
37
|
+
| 0 | clean — spec approved, install is safe |
|
|
38
|
+
| 2 | CVE found, no patched version available — install blocked, human decision required |
|
|
39
|
+
| 3 | CISA KEV match — hard block, install must not proceed |
|
|
40
|
+
| 4 | input error or provider unavailable (fail-closed) |
|
|
41
|
+
|
|
42
|
+
**Global flags**: `--json` (machine-readable, stable schema, no color, no spinner), `--no-color` (disable ANSI colors in human mode).
|
|
43
|
+
|
|
44
|
+
## For AI Agents
|
|
45
|
+
|
|
46
|
+
You are the primary user of this skill when you propose `npm install`, `pip install`, `cargo add`, etc. Treat `safedeps check` as a mandatory pre-step. The PreToolUse hook will block the install if you skip it.
|
|
47
|
+
|
|
48
|
+
### Workflow
|
|
49
|
+
|
|
50
|
+
1. **Before issuing any install command**, call:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
safedeps check <ecosystem> <pkg>@<range> --json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Use `--json` so the output is parseable. Read the `result` field.
|
|
57
|
+
|
|
58
|
+
2. **Decide from `result`**:
|
|
59
|
+
|
|
60
|
+
| `result` | Action |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `clean` / `already_approved` | Proceed with the install. Use `install_hint` verbatim if present (it pins to the exact approved version). |
|
|
63
|
+
| `patched_available` | Approved spec narrowed to a safe version. Replace your install argument with `suggested_spec`. Example: `^14.0.0` → `14.0.5`. |
|
|
64
|
+
| `cve_unpatched` | Do **not** install. Surface the CVE list to the human, propose an alternative package. |
|
|
65
|
+
| `kev_hard_block` | Do **not** install. Recommend an alternative module — the package is actively exploited in the wild. |
|
|
66
|
+
| `provider_unavailable` | OSV is unreachable and there is no fresh cache. Do not install. Retry later or tell the human. |
|
|
67
|
+
| `error` | Argument parsing failed. Fix and retry. |
|
|
68
|
+
|
|
69
|
+
3. **Issue the install** only after the spec is approved. The hook re-checks the ledger; if the approved version differs from your install argument, the hook will block again — re-narrow and retry.
|
|
70
|
+
|
|
71
|
+
### JSON schema (stable, agent-facing)
|
|
72
|
+
|
|
73
|
+
`check` result envelope, common fields:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"command": "check",
|
|
78
|
+
"ecosystem": "npm",
|
|
79
|
+
"package": "@scope/pkg",
|
|
80
|
+
"input_range": "^1.2.0",
|
|
81
|
+
"resolved_version": "1.2.4",
|
|
82
|
+
"result": "clean | already_approved | patched_available | cve_unpatched | kev_hard_block | patched_still_vulnerable | provider_unavailable",
|
|
83
|
+
"approved": true,
|
|
84
|
+
"spec_hash": "sha256:...",
|
|
85
|
+
"expires_at": "2026-06-17T05:39:03Z",
|
|
86
|
+
"install_hint": "install with @scope/pkg@1.2.4"
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`patched_available` adds `"suggested_spec": "1.2.5"`. `kev_hard_block` retains the full `vulnerabilities` and `kev.matches` arrays for evidence. `cve_unpatched` retains `vulnerabilities`.
|
|
91
|
+
|
|
92
|
+
`ledger` returns `{ "command": "ledger", "count": N, "specs": [...] }` where each spec has `hash`, `ecosystem`, `package`, `version`, `version_range`, `approved_at`, `expires_at`, `approved_by`, `expired` (bool), `revoked` (bool).
|
|
93
|
+
|
|
94
|
+
`revoke` returns `{ "command": "revoke", "revoked": true, "reason": "...", "spec": {...} }`.
|
|
95
|
+
|
|
96
|
+
`re-check` returns `{ "command": "re-check", "checked": N, "still_clean": N, "newly_vulnerable": [...], "kev_hit": [...], "revoked": [...] }`.
|
|
97
|
+
|
|
98
|
+
`migrate` returns `{ "migrated": bool, "legacyRoot": "...", "targetRoot": "...", "copied": N, "skipped": N, "archivedAs": "..." }`.
|
|
99
|
+
|
|
100
|
+
### When the hook blocks you
|
|
101
|
+
|
|
102
|
+
`scripts/safedeps-pre-guard.sh` emits a Claude Code / Codex CLI hook decision using the modern PreToolUse schema:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"hookSpecificOutput": {
|
|
107
|
+
"hookEventName": "PreToolUse",
|
|
108
|
+
"permissionDecision": "deny",
|
|
109
|
+
"permissionDecisionReason": "safedeps: install not approved (ecosystem=npm) — run `safedeps check npm @scope/pkg@^1.2.0` first, then retry the install using the approved version (see install_hint in the check output)."
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Both engines surface `permissionDecisionReason` back to you as the block message. Run the `safedeps check ...` command quoted inside backticks, parse the `--json` output, and retry the install with the approved version.
|
|
115
|
+
|
|
116
|
+
### Hard rules
|
|
117
|
+
|
|
118
|
+
- Never bypass the advisory gate. There is no silent fallback. If the provider is unreachable, fail-closed is the correct outcome.
|
|
119
|
+
- KEV (`result: "kev_hard_block"`) is non-negotiable. Recommend an alternative; do not ask the human to override.
|
|
120
|
+
- Use `install_hint` or `suggested_spec` verbatim. Do not rewrite the version with a fresh range — that defeats the spec lock.
|
|
121
|
+
|
|
122
|
+
## For Humans
|
|
123
|
+
|
|
124
|
+
Default output is Korean + ANSI color + braille spinner during long calls. Designed for terminal use, no flags needed.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
$ safedeps check npm "@scope/pkg@^14.0.0"
|
|
128
|
+
· 버전 해석 중 (@scope/pkg@^14.0.0)
|
|
129
|
+
· 취약점 조회 중 (OSV / KEV / GHSA)
|
|
130
|
+
⚠ @scope/pkg@14.0.3 에 2 개 CVE — 안전 버전 14.0.5 으로 좁혀 재조회합니다.
|
|
131
|
+
· 14.0.5 재조회 중
|
|
132
|
+
✓ @scope/pkg@14.0.5 승인 (until 2026-06-17T...)
|
|
133
|
+
· ledger: sha256:abc123...
|
|
134
|
+
|
|
135
|
+
$ safedeps ledger
|
|
136
|
+
STATE ECOSYSTEM PACKAGE VERSION APPROVED EXPIRES HASH
|
|
137
|
+
ACTIVE npm @scope/pkg 14.0.5 2026-05-18T... 2026-06-17T... sha256:abc...
|
|
138
|
+
|
|
139
|
+
$ safedeps revoke @scope/pkg@14.0.5 --reason "team policy change"
|
|
140
|
+
✓ 취소: npm @scope/pkg@14.0.5
|
|
141
|
+
|
|
142
|
+
$ safedeps re-check
|
|
143
|
+
· 재검증 npm left-pad@1.3.0
|
|
144
|
+
· 검증 완료: 1 개 중 1 개 clean
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Color legend
|
|
148
|
+
|
|
149
|
+
- `· gray` — info / progress
|
|
150
|
+
- `✓ green` — safe, approved
|
|
151
|
+
- `⚠ yellow` — warning, manual decision required
|
|
152
|
+
- `✗ red` — hard error or KEV block
|
|
153
|
+
|
|
154
|
+
Disable color with `--no-color` or `NO_COLOR=1`. Non-TTY pipes also strip color automatically.
|
|
155
|
+
|
|
156
|
+
## Current Components
|
|
157
|
+
|
|
158
|
+
- `bin/safedeps` — CLI (this entry point). Bash. Source-loads providers + ledger libs.
|
|
159
|
+
- `lib/providers/providers.sh` — OSV / CISA KEV / GitHub Advisory adapters with a single query interface and 24h local cache under `~/.safedeps/cache/`.
|
|
160
|
+
- `lib/ledger/ledger.sh` — approved spec JSON ledger I/O under `~/.safedeps/approved-specs/`, deterministic spec hash, TTL checks, atomic writes.
|
|
161
|
+
- `scripts/safedeps-pre-guard.sh` — PreToolUse hook. v1 command pattern guard + ledger lookup for install commands.
|
|
162
|
+
- `scripts/safedeps-post-verify.sh` — PostToolUse hook. v1 rollback engine + approved-spec diff.
|
|
163
|
+
- `scripts/install/install-safedeps-hooks.mjs` — cross-engine installer. Symlinks `~/.claude/skills/safedeps` and `~/.codex/skills/safedeps`, idempotently patches `~/.claude/settings.json` and `~/.codex/hooks.json`. `--uninstall` removes both.
|
|
164
|
+
|
|
165
|
+
## Provider Failure Policy
|
|
166
|
+
|
|
167
|
+
- OSV.dev is primary. Fresh cache may be used for 24h; cache miss or stale cache on OSV failure is fail-closed (`safedeps check` exits 4, hook blocks).
|
|
168
|
+
- CISA KEV is an overlay. Stale or unavailable catalog is surfaced as a warning/status, not hidden.
|
|
169
|
+
- GitHub Advisory is enrichment. Failure is fail-open only with an observable skipped status and advisory log entry.
|
|
170
|
+
|
|
171
|
+
## Installation
|
|
172
|
+
|
|
173
|
+
The cross-engine installer registers the skill + hooks for Claude Code and Codex CLI in one shot. It is idempotent and backs up `settings.json` / `hooks.json` before writing.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
node scripts/install/install-safedeps-hooks.mjs # install
|
|
177
|
+
node scripts/install/install-safedeps-hooks.mjs --uninstall # remove
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
What it does:
|
|
181
|
+
|
|
182
|
+
- Symlink the repo at `~/.claude/skills/safedeps` (when `~/.claude` exists) and `~/.codex/skills/safedeps` (when `~/.codex` exists).
|
|
183
|
+
- Patch `~/.claude/settings.json` `hooks.PreToolUse[matcher=Bash]` and `hooks.PostToolUse[matcher=Bash]` with the canonical script paths.
|
|
184
|
+
- Patch `~/.codex/hooks.json` with the same matcher and paths.
|
|
185
|
+
- Optionally symlink `~/.local/bin/safedeps -> bin/safedeps` so the CLI is on PATH.
|
|
186
|
+
|
|
187
|
+
Manual registration is also supported — see [Claude Code Hooks reference](https://code.claude.com/docs/en/hooks) and [Codex CLI Hooks](https://developers.openai.com/codex/hooks). The canonical script paths are:
|
|
188
|
+
|
|
189
|
+
- PreToolUse: `<skills-root>/safedeps/scripts/safedeps-pre-guard.sh`
|
|
190
|
+
- PostToolUse: `<skills-root>/safedeps/scripts/safedeps-post-verify.sh`
|
|
191
|
+
|
|
192
|
+
## State
|
|
193
|
+
|
|
194
|
+
- Approved specs: `~/.safedeps/approved-specs/`
|
|
195
|
+
- Provider cache: `~/.safedeps/cache/`
|
|
196
|
+
- Reorg snapshots: `~/.safedeps/snapshots/`
|
|
197
|
+
- Advisory log: `~/.safedeps/advisory.log`
|
|
198
|
+
- Reorg log: `~/.safedeps/reorg.log`
|
|
199
|
+
|
|
200
|
+
`safedeps` is the canonical skill name, state namespace, and repository name.
|