skill-vet-cli 1.0.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jasveer Singh
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,345 @@
1
+ Metadata-Version: 2.4
2
+ Name: skill-vet-cli
3
+ Version: 1.0.0
4
+ Summary: Vet an agent skill pack before you install it — stealing, spying and hidden sending, proven with file-and-line evidence.
5
+ Author: Jasveer Singh
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/jasveerai88/skill-vet
8
+ Project-URL: Repository, https://github.com/jasveerai88/skill-vet
9
+ Project-URL: Issues, https://github.com/jasveerai88/skill-vet/issues
10
+ Project-URL: Changelog, https://github.com/jasveerai88/skill-vet/blob/main/CHANGELOG.md
11
+ Keywords: agent-skills,claude-code,ai-agents,security,static-analysis,cli
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Security
21
+ Classifier: Topic :: Software Development :: Quality Assurance
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Dynamic: license-file
26
+
27
+ <h1 align="center">skill-vet</h1>
28
+
29
+ <p align="center"><strong>Vet an agent skill before you install it — stealing, spying, hidden sending, proven with file-and-line evidence.</strong></p>
30
+
31
+ <p align="center">
32
+ <img alt="tests: 44 passing" src="https://img.shields.io/badge/tests-44%20passing-brightgreen">
33
+ <img alt="python 3.10 | 3.11 | 3.12" src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue">
34
+ <img alt="version 1.0.0" src="https://img.shields.io/badge/version-1.0.0-orange">
35
+ <img alt="dependencies: none" src="https://img.shields.io/badge/dependencies-0-brightgreen">
36
+ <img alt="license: MIT" src="https://img.shields.io/badge/license-MIT-blue">
37
+ </p>
38
+
39
+ <p align="center"><img alt="skill-vet demo: a clean pack passes, a hostile pack is BLOCKED with three danger findings" src="docs/demo.gif" width="880"></p>
40
+
41
+ A skill pack runs with your agent's permissions the moment it is
42
+ installed. Per-file linters check the SKILL.md's formatting; nobody
43
+ vets the whole directory — the frontmatter, the referenced files, and
44
+ above all the scripts. The marketplace numbers say why this matters:
45
+ Snyk's ToxicSkills audit (Feb 2026) found security flaws in 1,467
46
+ of 3,984 marketplace skills (36.8%) and confirmed 76 with active
47
+ malicious payloads on manual review. VirusTotal analysed 35,878 skills and
48
+ found 6,637 malicious — most of them hiding the payload in plain
49
+ sentences or concealment mechanics rather than obvious malware.
50
+ skill-vet is the local, deterministic first pass over a pack you were
51
+ handed, before it gets anywhere near your agent.
52
+
53
+ **Static and read-only — it executes nothing.** Vet never imports,
54
+ runs, compiles, or decodes anything in the pack. Every file is read
55
+ as text and judged as evidence. Its own source imports no network or
56
+ subprocess module, and the test suite proves the read-only claim
57
+ twice: a fixture script that would write a marker file if it ran
58
+ never runs, and every fixture tree comes out byte-identical after an
59
+ audit.
60
+
61
+ ## Quick start
62
+
63
+ ```bash
64
+ pipx install git+https://github.com/jasveerai88/skill-vet # or: pip install git+https://github.com/jasveerai88/skill-vet
65
+ skill-vet vet ~/Downloads/some-skill
66
+ ```
67
+
68
+ That's the whole workflow: one command, one report, an exit code you
69
+ can gate on — **1** = BLOCKED (do not install), **0** = CLEAN or
70
+ REVIEW, **2** = input error. Add `--json` for a machine-readable
71
+ report, `--strict` to also fail on REVIEW. From a source checkout,
72
+ `python3 src/skill_vet.py vet <pack>` does the same thing. Python
73
+ 3.10+, standard library only, no dependencies.
74
+
75
+ ## What it catches
76
+
77
+ A pack is DANGEROUS only if it does one of three things — and each
78
+ verdict needs the **combination** of evidence in the same file, both
79
+ halves cited. A pattern hit alone is never a danger verdict.
80
+
81
+ | Catch | What has to be true | Real example (from `examples/`) |
82
+ |---|---|---|
83
+ | **Stealing** | A script reads credential stores, SSH keys, browser profiles, or environment secrets **and** sends or copies them out | `hostile-skill/scripts/collect.py` reads an SSH key (line 12) and POSTs it (line 18) → `DANGER_STEALING` |
84
+ | **Spying** | A script captures screen, keyboard, microphone, camera, or browser history **and** persists or sends it, undisclosed in the docs | `hostile-skill/scripts/snoop.py` screenshots in a loop (line 12) and POSTs the shots (line 15) → `DANGER_SPYING` |
85
+ | **Hidden sending** | A network call whose payload or destination is concealed — an encoded payload, local file contents to an undisclosed endpoint, or any send from a pack that claims to work offline | `hostile-skill/scripts/report.py` base64-encodes a documents file (line 14) and POSTs it to an endpoint the docs never mention (line 15) → `DANGER_HIDDEN_SENDING` |
86
+ | **Structure errors** | SKILL.md missing or unparseable, required fields absent, referenced files that don't exist | `sloppy-skill`'s SKILL.md links `references/checklist.md`, which is not in the pack → `BROKEN_REFERENCE` |
87
+ | **Short of danger** | One ingredient without its combination: a credential read with no way out, an undisclosed endpoint on its own, `shell=True`, an opaque base64 blob, invisible characters | `sloppy-skill` earns 4 warnings and a REVIEW verdict — not a block — and its one honest, documented network call earns no finding at all |
88
+
89
+ Verdicts: **BLOCKED** (at least one danger finding), **REVIEW** (no
90
+ danger, but at least one error or warning), **CLEAN** (no errors or
91
+ warnings; INFO may remain). The verdict rule is printed on every
92
+ report. REVIEW exits 0 on purpose: REVIEW means "a human should read
93
+ this", and a gate that fails on warnings trains people to bypass the
94
+ gate. `--strict` is there for those who disagree.
95
+
96
+ [Quick start](#quick-start) · [What it catches](#what-it-catches) ·
97
+ [How it compares](#how-it-compares) · [Reference](#reference)
98
+
99
+ ## How it compares
100
+
101
+ | | **skill-vet** | Per-file SKILL.md linter | Installing blind |
102
+ |---|---|---|---|
103
+ | Scope | The whole pack: frontmatter, references, inventory, every script | The SKILL.md file only | — |
104
+ | Danger model | Stealing / spying / hidden sending, each proven as a combination | Formatting and schema only | None |
105
+ | Evidence | Every finding cites file + line, both halves of a combination | Line-level style notes | — |
106
+ | Executes the pack? | Never — static text analysis only | No | Yes, with your agent's permissions |
107
+ | A lone suspicious pattern | A warning, never a block | n/a | n/a |
108
+ | Output | Text report + `--json`, exit codes for CI | Varies | — |
109
+ | Dependencies | 0 (Python 3.10+ stdlib) | Varies | — |
110
+
111
+ ## Honest limits (the short version)
112
+
113
+ Static patterns are evidence, not proof. A pack that assembles its
114
+ behaviour at runtime, splits a danger combination across two files
115
+ (combinations are judged per file), or writes its social engineering
116
+ in plain, honest sentences can pass. A bundled binary is flagged
117
+ precisely because vet can say nothing about what it does when run. A
118
+ CLEAN verdict means *no pattern fired* — it cannot prove a pack safe,
119
+ and every report says so. The full limits are
120
+ [below](#honest-limits).
121
+
122
+ ---
123
+
124
+ ## Reference
125
+
126
+ **Contents:** [What it checks](#what-it-checks) ·
127
+ [Full reports: hostile](#a-hostile-pack--one-file-per-danger-test) ·
128
+ [sloppy](#a-sloppy-pack--careless-not-malicious) ·
129
+ [clean](#a-clean-pack) · [For agents](#for-agents) ·
130
+ [Tests](#tests) · [Honest limits](#honest-limits)
131
+
132
+ ### What it checks
133
+
134
+ | Area | Rules |
135
+ |---|---|
136
+ | Structure | `MISSING_SKILL_MD` / `SKILL_MD_CASE` — no SKILL.md at the root, or under a differently-cased name. `FRONTMATTER_MISSING` / `FRONTMATTER_PARSE` — no `---` block, or a line outside the stated subset. `REQUIRED_FIELD` — `name` or `description` missing or empty. `NAME_DIR_MISMATCH` / `NAME_FORMAT` — name ≠ folder, or not a kebab-case slug. `BROAD_TOOL_GRANT` — an `allowed-tools` entry of `*`, `Tool(*)`, or bare `Bash`. |
137
+ | References | `BROKEN_REFERENCE` (ERROR) — a local file referenced from SKILL.md (link or backticked path) or from a script (path literal) does not exist. `REFERENCE_OUTSIDE_PACK` — a reference resolving outside the pack. |
138
+ | Inventory | Every file listed with kind and size. `LARGE_FILE` — over 1 MiB. `BUNDLED_BINARY` — a binary, which cannot be statically vetted at all. `SYMLINK_OUT` (INFO) — a symlink leaving the pack; its target is not scanned. `INSTALL_HOOK` — a file that runs at install time (setup.py, .pth, install scripts, package.json hooks). |
139
+ | Danger (BLOCKED) | `DANGER_STEALING`, `DANGER_SPYING`, `DANGER_HIDDEN_SENDING` — only on the combinations described above, both halves cited. |
140
+ | Short of danger | `SECRET_ACCESS` (credential read, no egress), `UNDISCLOSED_NETWORK` (endpoint the docs never mention), `DYNAMIC_ENDPOINT` (no literal URL to check), `ENCODED_PAYLOAD` (encoded payload to a *disclosed* endpoint), `DISCLOSED_CAPTURE` (capture the docs admit to), `CAPTURE_CAPABILITY` (capture API, no persistence or send). |
141
+ | Hygiene | `HYGIENE_SHELL_TRUE`, `HYGIENE_DYNAMIC_EXEC` (eval / exec / os.system), `HYGIENE_DOWNLOAD_EXEC` (`curl … \| sh`, or download + exec), `HYGIENE_OBFUSCATION` (base64 / hex blobs, `\x` escape runs), `CONCEALED_UNICODE` (invisible characters, cited by name), `CONCEALED_BLANK_RUN` (50+ blank lines with content after), `HIDDEN_COMMENT` (120+ char HTML comments), `WRITES_OUTSIDE_PACK`. |
142
+
143
+ The full rule table — severities, the exact evidence each check
144
+ rests on, the disclosure model, and the judgement calls — is in
145
+ [SKILL.md](SKILL.md).
146
+
147
+ ### A hostile pack — one file per danger test
148
+
149
+ `examples/hostile-skill/` is a constructed pack whose three helper
150
+ scripts each trip one danger test: one reads an SSH key and an AWS
151
+ secret and posts them out, one screenshots the desktop in a loop and
152
+ posts the shots, one reads a documents file, base64-encodes it, and
153
+ posts it to an endpoint the docs never mention. Every endpoint is an
154
+ `.invalid` name — fictional by design. Verbatim output:
155
+
156
+ ```
157
+ $ skill-vet vet examples/hostile-skill
158
+ skill-vet v1.0.0 — vet · pack hostile-skill · 4 files · 1.6 KiB total
159
+ Frontmatter name: hostile-skill
160
+ Read-only: it edits nothing, writes nothing, and never executes anything in the pack — every file is analysed as static text.
161
+ Verdict rule: BLOCKED = at least one danger finding (a proven stealing / spying / hidden-sending combination); REVIEW = no danger finding, but at least one ERROR or WARN; CLEAN = no ERROR or WARN findings (INFO may remain). Exit 1 only for BLOCKED (or for REVIEW with --strict); exit 2 is an input error.
162
+ Limits: Static pattern analysis only: it reads evidence, it cannot prove a pack safe. A CLEAN verdict means no pattern fired — plain-sight social engineering, a payload assembled at runtime, and bundled binaries can all pass a static vet.
163
+
164
+ INVENTORY (4 files):
165
+ SKILL.md — markdown · 428 B
166
+ scripts/collect.py — script · 448 B
167
+ scripts/report.py — script · 350 B
168
+ scripts/snoop.py — script · 398 B
169
+
170
+ DANGER — proven stealing / spying / hidden-sending combinations (3):
171
+ [DANGER_STEALING] scripts/collect.py · line 12
172
+ STEALING combination: this file reads secrets (an SSH key or .ssh store path, line 12) and has an egress path (an HTTP client call, line 18). Credential material plus a way out is the stealing test — the pack can take what it reads off the machine.
173
+ fix: do not install; if you maintain this pack, remove the credential read or the egress — a legitimate pack needs at most one of them
174
+ [DANGER_HIDDEN_SENDING] scripts/report.py · line 15
175
+ HIDDEN-SENDING combination: an encoded payload reaches the network call (encoder at line 14, send at line 15) to an endpoint the docs never disclose — neither what is sent nor where it goes can be read off the pack. Concealment of what is sent, or to where, is the hidden-sending test.
176
+ fix: do not install until the send is disclosed in the docs and the payload is readable in the code
177
+ [DANGER_SPYING] scripts/snoop.py · line 12
178
+ SPYING combination: this file captures screen (a screenshot call, line 12), persists or sends it (an HTTP client call, line 15), and the pack's docs nowhere disclose screen capture — capture plus a way to keep or move it, in secret, is the spying test.
179
+ fix: do not install; undisclosed capture is never a feature
180
+
181
+ Summary: 3 findings · 3 errors · 0 warnings · 0 info · 3 danger
182
+ Verdict: BLOCKED — 3 proven danger combination(s) (stealing / spying / hidden sending). Do not install.
183
+ (exit code 1)
184
+ ```
185
+
186
+ Note what is *not* there: no structure findings (the frontmatter is
187
+ valid and every referenced helper exists), and the collector's send
188
+ is judged once — as the egress half of stealing — not counted a
189
+ second time as hidden sending.
190
+
191
+ ### A sloppy pack — careless, not malicious
192
+
193
+ `examples/sloppy-skill/` is the opposite case: a pack that is merely
194
+ badly put together. A broken reference, a name that doesn't match
195
+ its folder, an invisible character in the SKILL.md, `shell=True`, an
196
+ opaque base64 blob — and one perfectly honest network call,
197
+ disclosed in its docs, which earns no finding at all:
198
+
199
+ ```
200
+ $ skill-vet vet examples/sloppy-skill
201
+ skill-vet v1.0.0 — vet · pack sloppy-skill · 2 files · 1022 B total
202
+ Frontmatter name: sloppy-helper
203
+ Read-only: it edits nothing, writes nothing, and never executes anything in the pack — every file is analysed as static text.
204
+ Verdict rule: BLOCKED = at least one danger finding (a proven stealing / spying / hidden-sending combination); REVIEW = no danger finding, but at least one ERROR or WARN; CLEAN = no ERROR or WARN findings (INFO may remain). Exit 1 only for BLOCKED (or for REVIEW with --strict); exit 2 is an input error.
205
+ Limits: Static pattern analysis only: it reads evidence, it cannot prove a pack safe. A CLEAN verdict means no pattern fired — plain-sight social engineering, a payload assembled at runtime, and bundled binaries can all pass a static vet.
206
+
207
+ INVENTORY (2 files):
208
+ SKILL.md — markdown · 450 B
209
+ scripts/tidy.py — script · 572 B
210
+
211
+ ERRORS — structure and references that do not work as shipped (1):
212
+ [BROKEN_REFERENCE] SKILL.md · line 15
213
+ referenced local file 'references/checklist.md' does not exist in the pack — the pack points at something that is not there
214
+ fix: add the file, or fix the reference
215
+
216
+ WARNINGS — short of danger, worth a human look (4):
217
+ [NAME_DIR_MISMATCH] SKILL.md
218
+ frontmatter name 'sloppy-helper' does not match the pack folder name 'sloppy-skill' — loaders and humans will call this pack two different things
219
+ fix: make the name and the folder agree
220
+ [CONCEALED_UNICODE] SKILL.md · line 16
221
+ 1 invisible character(s) in this file (first at line 16): ZERO WIDTH SPACE — invisible text can carry instructions a reader never sees
222
+ fix: strip invisible characters from pack files
223
+ [HYGIENE_OBFUSCATION] scripts/tidy.py · line 11
224
+ a base64 blob of 120+ characters at line 11 — content encoded as one opaque blob cannot be reviewed as written
225
+ fix: keep pack content readable; encoded blobs belong in the open or not at all
226
+ [HYGIENE_SHELL_TRUE] scripts/tidy.py · line 20
227
+ subprocess runs with shell=True — command strings become shell input, so any value that reaches the command is an injection path
228
+ fix: use an argument list with shell=False
229
+
230
+ Summary: 5 findings · 1 errors · 4 warnings · 0 info · 0 danger
231
+ Verdict: REVIEW — no danger combination found, but 1 error(s) and 4 warning(s) need a human look before installing.
232
+ (exit code 0 — REVIEW; exit 1 with --strict)
233
+ ```
234
+
235
+ ### A clean pack
236
+
237
+ ```
238
+ $ skill-vet vet examples/tidy-notes
239
+ skill-vet v1.0.0 — vet · pack tidy-notes · 3 files · 2.5 KiB total
240
+ Frontmatter name: tidy-notes
241
+ Read-only: it edits nothing, writes nothing, and never executes anything in the pack — every file is analysed as static text.
242
+ Verdict rule: BLOCKED = at least one danger finding (a proven stealing / spying / hidden-sending combination); REVIEW = no danger finding, but at least one ERROR or WARN; CLEAN = no ERROR or WARN findings (INFO may remain). Exit 1 only for BLOCKED (or for REVIEW with --strict); exit 2 is an input error.
243
+ Limits: Static pattern analysis only: it reads evidence, it cannot prove a pack safe. A CLEAN verdict means no pattern fired — plain-sight social engineering, a payload assembled at runtime, and bundled binaries can all pass a static vet.
244
+
245
+ INVENTORY (3 files):
246
+ SKILL.md — markdown · 790 B
247
+ references/style-guide.md — markdown · 392 B
248
+ scripts/summarize.py — script · 1.3 KiB
249
+
250
+ No findings — no structure errors, no danger combination, no hygiene warning fired. (Absence of findings is not proof of safety.)
251
+ Summary: 0 findings · 0 errors · 0 warnings · 0 info · 0 danger
252
+ Verdict: CLEAN — no errors, no warnings, no danger combinations found by the static rules.
253
+ (exit code 0)
254
+ ```
255
+
256
+ ### For agents
257
+
258
+ `--json` emits one object: the pack record, the full file inventory
259
+ (`path`, `bytes`, `kind`, `binary`, `scanned`, `symlink_out`),
260
+ findings (`rule`, `severity`, `danger`, `file`, `line`, `message`,
261
+ `fix`), summary counts that recount exactly against the findings,
262
+ the verdict, the verdict rule, and the limits statement. Input
263
+ errors — including argument errors — are a single JSON object with
264
+ an `error` key and exit 2. [SKILL.md](SKILL.md) states the full
265
+ combination table, the disclosure model, the frontmatter subset,
266
+ and what the tool deliberately does not claim — and makes skill-vet
267
+ itself installable as a skill: point your agent at this repo's
268
+ SKILL.md and it will vet packs before installing them.
269
+
270
+ ### Tests
271
+
272
+ ```
273
+ python3 -m unittest discover -s tests
274
+ ```
275
+
276
+ 44 tests: the three fixtures pinned to hand-counted tables; every
277
+ danger test in both directions (the combination fires BLOCKED; each
278
+ ingredient alone — secret read, undisclosed call, documented call,
279
+ capture alone, disclosed capture, encoded payload to a disclosed
280
+ endpoint — earns at most a warning); structure rules both
281
+ directions; verdict and exit-code boundaries including `--strict`;
282
+ JSON recount; and the safety proofs — nothing in a pack is ever
283
+ executed (a booby-trapped fixture's marker never appears), fixture
284
+ trees are byte-identical after runs, and the source's imports are
285
+ pinned to a stdlib set with no network or subprocess module.
286
+
287
+ ### Honest limits
288
+
289
+ - **Static patterns are evidence, not proof.** Vet reads what a
290
+ pack's text shows. A pack that assembles its behaviour at runtime
291
+ from innocuous pieces, splits a danger combination across two
292
+ files (combinations are judged per file), or writes its social
293
+ engineering in plain, honest sentences can pass. A CLEAN verdict
294
+ means no pattern fired — it cannot prove a pack safe, and every
295
+ report says so.
296
+ - **Binaries are out of reach.** A bundled binary is flagged
297
+ precisely because vet can say nothing about what it does when run.
298
+ - **Disclosure is judged on two documents.** What counts as "the
299
+ docs" is the pack root's SKILL.md and README.md — the two files an
300
+ installer is expected to have read. An endpoint disclosed only in
301
+ a third file counts as undisclosed.
302
+ - **The frontmatter parser is a subset.** Scalars, inline and block
303
+ lists, folded continuations. A line outside the subset is reported
304
+ as a parse error, never guessed at — a pack using exotic YAML will
305
+ need that line read by a human.
306
+ - **Pattern tables are a snapshot.** New capture libraries,
307
+ credential stores, and client APIs appear constantly; the tables
308
+ are dated by the release, not treated as complete.
309
+ - **Some SKILL.md formats have no frontmatter.** Packs shipped in
310
+ formats that register a skill without a `---` block will be
311
+ reported FRONTMATTER_MISSING — which is the finding working as
312
+ designed: vet judges the frontmatter format, and says so when it
313
+ is absent.
314
+
315
+ ## Contributing
316
+
317
+ See [CONTRIBUTING.md](CONTRIBUTING.md). The combination discipline
318
+ is the product: a lone pattern never becomes a BLOCKED verdict, and
319
+ contributions are held to that. Found a pack skill-vet misjudges —
320
+ a combination it misses or a warning it shouldn't fire? Open an
321
+ issue with the pack (or a minimal fixture); that is exactly the
322
+ feedback that improves the pattern tables.
323
+
324
+ ## Security
325
+
326
+ skill-vet is itself a security tool, so its own posture is simple:
327
+ it has no network code, no subprocess code, no dependencies, and it
328
+ never executes what it scans. See [SECURITY.md](SECURITY.md) for how
329
+ to report a problem.
330
+
331
+ ## License
332
+
333
+ MIT — see [LICENSE](LICENSE).
334
+
335
+ ## Related
336
+
337
+ - [permission-audit](https://github.com/jasveerai88/permission-audit)
338
+ — the other half of pre-flight for agent setups: audits a
339
+ Claude Code permission allowlist for wildcard grants and
340
+ dangerous modes before they hurt you.
341
+
342
+ ## Support
343
+
344
+ If skill-vet stops a bad install, consider
345
+ [sponsoring](https://github.com/sponsors/jasveerai88).