@exelerus/openclaw-vexscan 1.0.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/CLAUDE.md +112 -0
- package/README.md +149 -0
- package/SKILL.md +129 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +466 -0
- package/dist/index.js.map +1 -0
- package/dist/src/cli-wrapper.d.ts +18 -0
- package/dist/src/cli-wrapper.d.ts.map +1 -0
- package/dist/src/cli-wrapper.js +151 -0
- package/dist/src/cli-wrapper.js.map +1 -0
- package/dist/src/types.d.ts +48 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/index.ts +499 -0
- package/openclaw.plugin.json +52 -0
- package/package.json +44 -0
- package/src/cli-wrapper.ts +177 -0
- package/src/openclaw-sdk.d.ts +84 -0
- package/src/types.ts +53 -0
- package/tsconfig.json +18 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# OpenClaw Plugin Development
|
|
2
|
+
|
|
3
|
+
## Plugin API (verified against OpenClaw 2026.2.x)
|
|
4
|
+
|
|
5
|
+
The official docs are outdated. These are the actual patterns from the installed Gateway.
|
|
6
|
+
|
|
7
|
+
### Export Pattern
|
|
8
|
+
|
|
9
|
+
Two valid patterns — use the object form when the plugin has metadata:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// Object with register method (preferred for plugins with metadata)
|
|
13
|
+
const myPlugin = {
|
|
14
|
+
id: "my-plugin",
|
|
15
|
+
name: "My Plugin",
|
|
16
|
+
kind: "tool" as const,
|
|
17
|
+
configSchema: MySchema,
|
|
18
|
+
register(api: OpenClawPluginApi) { ... },
|
|
19
|
+
};
|
|
20
|
+
export default myPlugin;
|
|
21
|
+
|
|
22
|
+
// Bare function (simpler plugins)
|
|
23
|
+
export default function register(api: OpenClawPluginApi) { ... }
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Do NOT use:** `export const plugin`, named exports, or `init()` — the Gateway looks for a default export with a `register` method.
|
|
27
|
+
|
|
28
|
+
### Type Import
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The SDK type is `OpenClawPluginApi`, not `PluginContext` or `ToolPlugin` as docs suggest. Our `src/openclaw-sdk.d.ts` provides the ambient declaration so TypeScript compiles without the SDK installed.
|
|
35
|
+
|
|
36
|
+
### Plugin ID Must Match Package Name
|
|
37
|
+
|
|
38
|
+
The Gateway derives the plugin config key by stripping the npm scope from the package name:
|
|
39
|
+
- Package: `@exelerus/openclaw-vexscan` → config key: `openclaw-vexscan`
|
|
40
|
+
- The `id` in both `openclaw.plugin.json` and the plugin object **must** match this derived key
|
|
41
|
+
|
|
42
|
+
### Required Files
|
|
43
|
+
|
|
44
|
+
| File | Required | Purpose |
|
|
45
|
+
|------|----------|---------|
|
|
46
|
+
| `openclaw.plugin.json` | **Yes** | Discovery manifest (`id`, `kind`, `configSchema`) |
|
|
47
|
+
| `package.json` `openclaw.extensions` | Yes | Points Gateway to entry file |
|
|
48
|
+
| `index.ts` | Yes | Plugin entry with `register()` |
|
|
49
|
+
|
|
50
|
+
### Manifest (`openclaw.plugin.json`)
|
|
51
|
+
|
|
52
|
+
Uses `"kind"` not `"slots"`:
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"id": "openclaw-vexscan",
|
|
56
|
+
"kind": "tool",
|
|
57
|
+
"configSchema": { ... }
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Tool Registration
|
|
62
|
+
|
|
63
|
+
`api.registerTool()` accepts a plain object or a factory function:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// Plain object (our approach)
|
|
67
|
+
api.registerTool({
|
|
68
|
+
name: "vexscan",
|
|
69
|
+
description: "...",
|
|
70
|
+
parameters: TypeBoxSchema,
|
|
71
|
+
async execute(toolCallId, params) { return { content: [...] }; },
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Factory function (bundled plugin pattern)
|
|
75
|
+
api.registerTool(
|
|
76
|
+
(ctx) => createMyTool(api),
|
|
77
|
+
{ optional: true },
|
|
78
|
+
);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Config Schema
|
|
82
|
+
|
|
83
|
+
The manifest uses JSON Schema. The plugin object can use TypeBox (which is JSON Schema compatible). Config validation uses a Zod-like `safeParse` interface internally.
|
|
84
|
+
|
|
85
|
+
## Build & Test
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npm run build # Compile TypeScript
|
|
89
|
+
npm run clean # Remove dist/
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Testing with Live OpenClaw
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
openclaw setup # One-time: creates ~/.openclaw/openclaw.json
|
|
96
|
+
openclaw plugins install -l /path/to/plugins/openclaw # Symlink plugin
|
|
97
|
+
openclaw plugins list # Verify "loaded" status
|
|
98
|
+
openclaw vexscan --help # Test CLI registration
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
To uninstall: remove the plugin entry from `~/.openclaw/openclaw.json` under `plugins.entries`, `plugins.load.paths`, and `plugins.installs`.
|
|
102
|
+
|
|
103
|
+
### Peer Dependency
|
|
104
|
+
|
|
105
|
+
OpenClaw uses calendar versioning (e.g., `2026.2.3-1`). Peer dep is `>=2026.1.26`.
|
|
106
|
+
|
|
107
|
+
## Reference Plugins
|
|
108
|
+
|
|
109
|
+
Look at bundled plugins for real-world patterns:
|
|
110
|
+
- `~/.npm-global/lib/node_modules/openclaw/extensions/memory-core/` — object export, tool + CLI
|
|
111
|
+
- `~/.npm-global/lib/node_modules/openclaw/extensions/llm-task/` — function export, tool only
|
|
112
|
+
- SDK types: `~/.npm-global/lib/node_modules/openclaw/dist/plugin-sdk/index.d.ts`
|
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/edimuj/vexscan/main/assets/sir-clawsalot-256.png" alt="Sir Clawsalot" width="180">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Vexscan Plugin for OpenClaw</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Security scanner plugin that protects your OpenClaw environment from malicious extensions and skills.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@exelerus/openclaw-vexscan"><img src="https://img.shields.io/npm/v/@exelerus/openclaw-vexscan?style=flat-square&color=blue" alt="npm"></a>
|
|
13
|
+
<a href="../../LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-green?style=flat-square" alt="License"></a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **Automatic Scanning**: Scans third-party extensions on startup
|
|
19
|
+
- **Pre-Install Vetting**: Vet extensions before installing with `openclaw vexscan vet`
|
|
20
|
+
- **AI-Integrated**: The AI assistant can scan code on your behalf
|
|
21
|
+
- **Smart Filtering**: Skips official extensions, focuses on untrusted code
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
### Install the Plugin
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# From npm
|
|
29
|
+
openclaw plugins install @exelerus/openclaw-vexscan
|
|
30
|
+
|
|
31
|
+
# From local path
|
|
32
|
+
openclaw plugins install ./plugins/openclaw
|
|
33
|
+
|
|
34
|
+
# Development (symlink)
|
|
35
|
+
openclaw plugins install -l ./plugins/openclaw
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### CLI Installation (Optional)
|
|
39
|
+
|
|
40
|
+
The plugin will **auto-install** the Vexscan CLI on first run. For manual installation:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Quick install (macOS/Linux)
|
|
44
|
+
curl -fsSL https://raw.githubusercontent.com/edimuj/vexscan/main/install.sh | bash
|
|
45
|
+
|
|
46
|
+
# Or from source
|
|
47
|
+
git clone https://github.com/edimuj/vexscan && cd vexscan && cargo install --path .
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
### CLI Commands
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Scan installed extensions
|
|
56
|
+
openclaw vexscan scan
|
|
57
|
+
|
|
58
|
+
# Scan specific path
|
|
59
|
+
openclaw vexscan scan ~/.openclaw/extensions
|
|
60
|
+
|
|
61
|
+
# Vet before installing
|
|
62
|
+
openclaw vexscan vet https://github.com/user/cool-extension
|
|
63
|
+
|
|
64
|
+
# Vet and install in one step (blocked if critical/high findings)
|
|
65
|
+
openclaw vexscan install https://github.com/user/cool-extension
|
|
66
|
+
|
|
67
|
+
# Install with overrides
|
|
68
|
+
openclaw vexscan install ./local-extension --link # symlink for dev
|
|
69
|
+
openclaw vexscan install @org/extension --force # allow medium findings
|
|
70
|
+
openclaw vexscan install @org/extension --dry-run # vet only, don't install
|
|
71
|
+
|
|
72
|
+
# List detection rules
|
|
73
|
+
openclaw vexscan rules
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### AI Tool Usage
|
|
77
|
+
|
|
78
|
+
The AI assistant can use Vexscan directly:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
User: "Is this extension safe? https://github.com/user/extension"
|
|
82
|
+
AI: *uses vexscan tool to vet the extension*
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
User: "Check my extensions for security issues"
|
|
87
|
+
AI: *uses vexscan tool to scan ~/.openclaw/extensions*
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
User: "Install this extension: @org/cool-plugin"
|
|
92
|
+
AI: *uses vexscan install action to vet and install*
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
Configure in your `openclaw.json`:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"plugins": {
|
|
102
|
+
"vexscan": {
|
|
103
|
+
"enabled": true,
|
|
104
|
+
"scanOnInstall": true,
|
|
105
|
+
"minSeverity": "medium",
|
|
106
|
+
"thirdPartyOnly": true,
|
|
107
|
+
"skipDeps": true
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
| Option | Default | Description |
|
|
114
|
+
|------------------|----------|---------------------------------------------|
|
|
115
|
+
| `enabled` | `true` | Enable security scanning |
|
|
116
|
+
| `scanOnInstall` | `true` | Scan on startup |
|
|
117
|
+
| `minSeverity` | `medium` | Minimum severity to report |
|
|
118
|
+
| `thirdPartyOnly` | `true` | Only scan non-official extensions |
|
|
119
|
+
| `skipDeps` | `true` | Skip node_modules to reduce false positives |
|
|
120
|
+
| `ast` | `true` | AST analysis for obfuscation detection |
|
|
121
|
+
| `deps` | `true` | Dependency scanning for supply chain attacks|
|
|
122
|
+
| `cliPath` | (auto) | Path to vexscan binary |
|
|
123
|
+
|
|
124
|
+
## What It Detects
|
|
125
|
+
|
|
126
|
+
| Category | Examples |
|
|
127
|
+
|----------------------|-------------------------------------------------|
|
|
128
|
+
| Code Execution | `eval()`, `new Function()`, `exec()`, SQL injection |
|
|
129
|
+
| Shell Injection | `child_process`, `subprocess`, reverse shells |
|
|
130
|
+
| Data Exfiltration | Discord webhooks, external POST |
|
|
131
|
+
| Credential Access | SSH keys, AWS credentials |
|
|
132
|
+
| Hardcoded Secrets | API keys, tokens, passwords, connection strings |
|
|
133
|
+
| Prompt Injection | Instruction override, system prompt reveal |
|
|
134
|
+
| Obfuscation | Base64, hex encoding |
|
|
135
|
+
| Backdoor Detection | Time bombs, C2 callbacks |
|
|
136
|
+
| Dangerous Operations | `rm -rf`, `chmod 777`, `sudo` |
|
|
137
|
+
| Resource Abuse | Fork bombs, infinite loops |
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
cd plugins/openclaw
|
|
143
|
+
npm install
|
|
144
|
+
npm run build
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
Apache 2.0
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Vexscan Security Scanner
|
|
2
|
+
|
|
3
|
+
Vexscan scans extensions, skills, and code for security threats. Use it when:
|
|
4
|
+
|
|
5
|
+
- User wants to install a new extension or skill
|
|
6
|
+
- User asks about security of their OpenClaw setup
|
|
7
|
+
- User mentions suspicious behavior from an extension
|
|
8
|
+
- User wants to audit installed extensions
|
|
9
|
+
- Before recommending any third-party extension
|
|
10
|
+
|
|
11
|
+
## When to use Vexscan
|
|
12
|
+
|
|
13
|
+
| User intent | Action |
|
|
14
|
+
|--------------------------------------|---------------------------------------|
|
|
15
|
+
| "Install this extension from GitHub" | Use **install** — vets and installs |
|
|
16
|
+
| "Is this extension safe?" | Use **vet** — scan without installing |
|
|
17
|
+
| "Is my setup secure?" | Use **scan** — scan all extensions |
|
|
18
|
+
| "This extension is acting weird" | Use **scan** — scan for malicious patterns |
|
|
19
|
+
| "Show me my installed extensions" | No — use OpenClaw's built-in list |
|
|
20
|
+
|
|
21
|
+
## Install (vet + install in one step)
|
|
22
|
+
|
|
23
|
+
**Always prefer install over vet** when the user wants to add an extension. It vets first and only installs if the security check passes.
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"action": "install",
|
|
28
|
+
"source": "https://github.com/user/cool-extension"
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Returns on success:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"ok": true,
|
|
37
|
+
"action": "installed",
|
|
38
|
+
"findings": 0,
|
|
39
|
+
"message": "Installed — no security issues found."
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Returns when blocked:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"ok": false,
|
|
48
|
+
"action": "install_blocked",
|
|
49
|
+
"verdict": "high_risk",
|
|
50
|
+
"findings": 3,
|
|
51
|
+
"maxSeverity": "high",
|
|
52
|
+
"reason": "HIGH severity findings — installation blocked. Use allowHigh/--allow-high to override."
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Severity gates
|
|
57
|
+
|
|
58
|
+
| Max severity | Default | Override |
|
|
59
|
+
|-------------|------------|------------------|
|
|
60
|
+
| Critical | **Blocked** | Cannot override |
|
|
61
|
+
| High | **Blocked** | `"allowHigh": true` |
|
|
62
|
+
| Medium | **Blocked** | `"force": true` |
|
|
63
|
+
| Low / Info | Allowed | — |
|
|
64
|
+
|
|
65
|
+
**Never set `allowHigh` or `force` without explaining the risks to the user first.**
|
|
66
|
+
|
|
67
|
+
## Scan installed extensions
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"action": "scan",
|
|
72
|
+
"path": "~/.openclaw/extensions"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"ok": true,
|
|
81
|
+
"findings": 3,
|
|
82
|
+
"maxSeverity": "medium",
|
|
83
|
+
"summary": {
|
|
84
|
+
"critical": 0,
|
|
85
|
+
"high": 0,
|
|
86
|
+
"medium": 3,
|
|
87
|
+
"low": 1,
|
|
88
|
+
"info": 2
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Vet without installing
|
|
94
|
+
|
|
95
|
+
Use when the user just wants a security assessment:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"action": "vet",
|
|
100
|
+
"source": "https://github.com/user/cool-extension"
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"ok": true,
|
|
109
|
+
"verdict": "clean",
|
|
110
|
+
"findings": 0,
|
|
111
|
+
"message": "No security issues found"
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Verdicts
|
|
116
|
+
|
|
117
|
+
| Verdict | Meaning | Recommendation |
|
|
118
|
+
|-------------|----------------------|-----------------------------|
|
|
119
|
+
| `clean` | No issues found | Safe to install |
|
|
120
|
+
| `warnings` | Low/medium issues | Review findings, usually OK |
|
|
121
|
+
| `high_risk` | High severity issues | Warn user, review carefully |
|
|
122
|
+
| `dangerous` | Critical issues | Do NOT recommend installing |
|
|
123
|
+
|
|
124
|
+
## Important
|
|
125
|
+
|
|
126
|
+
- **Always use install** (not raw `openclaw plugins install`) so extensions are vetted first
|
|
127
|
+
- If install is blocked, explain the specific threats found
|
|
128
|
+
- Never override severity gates without user consent
|
|
129
|
+
- Third-party extensions are higher risk than official ones
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
|
+
declare const vexscanPlugin: {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
kind: "tool";
|
|
7
|
+
configSchema: import("@sinclair/typebox").TObject<{
|
|
8
|
+
enabled: import("@sinclair/typebox").TBoolean;
|
|
9
|
+
scanOnInstall: import("@sinclair/typebox").TBoolean;
|
|
10
|
+
minSeverity: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"info">, import("@sinclair/typebox").TLiteral<"low">, import("@sinclair/typebox").TLiteral<"medium">, import("@sinclair/typebox").TLiteral<"high">, import("@sinclair/typebox").TLiteral<"critical">]>;
|
|
11
|
+
thirdPartyOnly: import("@sinclair/typebox").TBoolean;
|
|
12
|
+
skipDeps: import("@sinclair/typebox").TBoolean;
|
|
13
|
+
ast: import("@sinclair/typebox").TBoolean;
|
|
14
|
+
deps: import("@sinclair/typebox").TBoolean;
|
|
15
|
+
cliPath: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
16
|
+
}>;
|
|
17
|
+
register(api: OpenClawPluginApi): void;
|
|
18
|
+
};
|
|
19
|
+
export default vexscanPlugin;
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAkH7D,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;kBAOH,iBAAiB;CAsXhC,CAAC;AAEF,eAAe,aAAa,CAAC"}
|