skill-scanner logo

skill-scanner

kobepaw/openclaw-skill-scanner

Otheropenclawby kobepaw

Summary

OpenClaw plugin exposing 0 skills.

Install to Claude Code

openclaw plugin add kobepaw/openclaw-skill-scanner

Run in Claude Code. Add the marketplace first with /plugin marketplace add kobepaw/openclaw-skill-scanner if you haven't already.

README.md

@kobepaw/openclaw-skill-scanner

> AST-based evasion detection for OpenClaw skills. > Catches obfuscation, dynamic eval, and encoding tricks that regex patterns miss.

![npm](https://www.npmjs.com/package/@kobepaw/openclaw-skill-scanner) ![License: Apache-2.0](LICENSE)

---

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 detected
  • setTimeout("code", 0) string eval not detected
  • Function.prototype.constructor("code")() not detected
  • Legitimate require(path.join(__dirname, "config")) will flag as dynamic-require — acceptable trade-off for security

---

Contributing

Issues and PRs welcome: github.com/kobepaw/openclaw-skill-scanner

---

License

Apache-2.0 © kobepaw

Related plugins

Browse all →