@kobepaw/openclaw-skill-scanner
> AST-based evasion detection for OpenClaw skills. > Catches obfuscation, dynamic eval, and encoding tricks that regex patterns miss.
 
---
What it catches
OpenClaw's built-in skill scanner uses regex patterns to detect dangerous code. But regex has a fundamental weakness: it matches strings, not structure. A malicious skill author can bypass regex by obfuscating their code.
This plugin adds a TypeScript AST analysis layer that catches structural evasion patterns:
| Rule ID | Severity | What it catches | |---------|----------|----------------| | dynamic-import | 🔴 critical | import(variable), import(\${template}\) — dynamic module loading | | dynamic-require | 🔴 critical | require(expr) with non-literal args — concatenated module names | | indirect-eval | 🔴 critical | globalThis"eval", (0, eval)(...), window.Function(...) | | prototype-pollution | 🔴 critical | __proto__ assignment, constructor.prototype, Object.setPrototypeOf() |
Real examples
These all bypass regex but are caught by this plugin:
// Concatenated require — regex sees no module name
const cp = require("child_" + "process");
cp.exec("whoami");
// Variable import — regex can't match the specifier
const target = getPayload();
await import(target);
// Indirect eval via comma operator — regex won't match "eval" as a call
(0, eval)("malicious code here");
// globalThis bracket notation — bypasses direct "eval" keyword check
globalThis["eval"]("malicious code here");
// Prototype pollution
obj["__proto__"]["isAdmin"] = true;
---
Install
openclaw plugins install @kobepaw/openclaw-skill-scanner
---
Configuration
Add to your OpenClaw config:
{
"plugins": {
"entries": {
"skill-scanner": {
"enabled": true,
"blockOnDetection": false
}
}
}
}
| Option | Type | Default | Description | |--------|------|---------|-------------| | enabled | boolean | true | Enable/disable AST scanning | | blockOnDetection | boolean | false | Block skill install on findings (warn-only by default) |
---
How it works
The plugin uses TypeScript's built-in parser (typescript package) — zero additional dependencies beyond what's already in your OpenClaw install.
When a skill is scanned: 1. TypeScript's createSourceFile parses the source into an AST 2. Four structural detectors walk the AST looking for dangerous patterns 3. Findings are reported with file path, line number, and evidence snippet 4. Deduplication: one finding per rule per file keeps output actionable, not noisy 5. Graceful degradation: if parsing fails, a warn-level ast-parse-error finding is emitted
---
Design decisions
- Complements, doesn't replace — works alongside existing regex scanners as a second layer
- Zero new dependencies — TypeScript is already a project dependency in most OpenClaw setups
- Correct ScriptKind mapping —
.tsx→TSX,.jsx→JSX,.js/.mjs/.cjs→JS, everything else→TS - One finding per ruleId per file — signal over noise
Known acceptable gaps
process.binding()native access not detectedsetTimeout("code", 0)string eval not detectedFunction.prototype.constructor("code")()not detected- Legitimate
require(path.join(__dirname, "config"))will flag asdynamic-require— acceptable trade-off for security
---
Contributing
Issues and PRs welcome: github.com/kobepaw/openclaw-skill-scanner
---
License
Apache-2.0 © kobepaw











