Install
openclaw skills install publish-skill-vettrStatic analysis security scanner for third-party OpenClaw skills. Detects eval/spawn risks, malicious dependencies, typosquatting, and prompt injection patterns before installation. Use when vetting skills from ClawHub or untrusted sources.
openclaw skills install publish-skill-vettrSecurity scanner for third-party OpenClaw skills. Analyses source code, dependencies, and metadata before installation using tree-sitter AST parsing and regex pattern matching.
npm install
This installs all Node.js dependencies, including tree-sitter .wasm grammar files required at runtime for AST-based analysis. The .wasm files are located in node_modules and must be present for the skill to function.
⚠️ Install safety:
npm installruns dependency lifecycle scripts, which can execute arbitrary code. For stronger isolation, runnpm ci --ignore-scripts— but note that tree-sitter native/WASM artifacts may not build, breaking AST analysis. Prefer installing inside a container or VM when possible.
The vet-url and vet-clawhub commands invoke external binaries via execSafe (which uses execFile — no shell is spawned). Only the following commands are permitted:
| Binary | Used By | Purpose |
|---|---|---|
git | vet-url | Clone .git URLs (with hooks disabled) |
curl | vet-url | Download archive URLs |
tar | vet-url | Extract downloaded archives |
clawhub | vet-clawhub | Fetch skills from ClawHub registry |
The /skill:vet command (local path vetting) requires only node and no external binaries.
/skill:vet --path <directory> — Vet a local skill directory/skill:vet-url --url <https://...> — Download and vet from URL/skill:vet-clawhub --skill <slug> — Fetch and vet from ClawHub| Category | Method | Examples |
|---|---|---|
| Code execution | AST | eval(), new Function(), vm.runInThisContext() |
| Shell injection | AST | exec(), execSync(), spawn("bash"), child_process imports |
| Dynamic require | AST | require(variable), require(templateString) |
| Prototype pollution | AST | proto assignment |
| Prompt injection | Regex | Instruction override patterns, control tokens (in string literals) |
| Homoglyph attacks | Regex | Cyrillic/Greek lookalike characters in identifiers |
| Encoded names | Regex | Unicode/hex-escaped "eval", "exec" |
| Credential paths | Regex | Cloud and SSH credential directory references, system credential store access |
| Network calls | AST | fetch() with literal URLs (checked against allowlist) |
| Malicious deps | Config | Known bad packages, lifecycle scripts, git/http deps |
| Typosquatting | Levenshtein | Skill names within edit distance 2 of targets |
| Dangerous permissions | Config | shell:exec, credentials:read in SKILL.md |
⚠️ This is a heuristic scanner with inherent limitations. It cannot guarantee safety.
fetch() with literal URL strings; misses axios, http module, dynamic URLsvet-url downloads and extracts remote archives into a temp directory; vet accepts paths under os.tmpdir(), ~/.openclaw, and ~/Downloads by default. Set allowCwd: true in config to also permit process.cwd() (see Configuration below)vet-url and vet-clawhub invoke git, curl, tar, and clawhub via execFile. These binaries must be trusted and present on PATHFor high-security environments, combine with sandboxing, network isolation, and manual source review. Run inside a disposable container when vetting untrusted URLs.
allowCwdBy default, process.cwd() is not included in the set of allowed vetting roots. The default allowed roots are:
os.tmpdir()~/.openclaw~/DownloadsTo allow vetting paths under the current working directory, set allowCwd: true in your vetting config:
{
"allowCwd": true
}
⚠️ Security implication: Enabling
allowCwdmeans the scanner will accept any path under the directory you launched it from. If you run from/or$HOME, this effectively grants access to your entire filesystem. Only enable this when running from a scoped project directory or inside a container.
.vettrignorePlace a .vettrignore file in the root of the skill directory being scanned to exclude files or directories from analysis. This is useful for excluding test fixtures that contain deliberate malicious patterns.
# are comments/ match entire directories* matches any sequence of non-separator characters** matches any sequence including path separators (recursive)? matches a single non-separator character# Exclude test fixtures containing deliberate prompt injection vectors
test/fixtures/
# Exclude generated files
dist/
*.min.js
If the .vettrignore file is unreadable or contains invalid UTF-8, the engine logs an INFO-level warning and proceeds with a full scan.