@pwddd/skills-scanner 3.0.6 → 3.0.8
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/README.md +12 -32
- package/index.ts +21 -17
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/skills/skills-scanner/SKILL.md +635 -640
- package/skills/skills-scanner/scan.py +12 -6
- package/src/commands.ts +302 -302
- package/src/deps.ts +77 -112
- package/src/report.ts +2 -2
- package/src/scanner.ts +6 -2
- package/src/watcher.ts +9 -9
package/README.md
CHANGED
|
@@ -116,29 +116,22 @@ openclaw skills-scanner health
|
|
|
116
116
|
|
|
117
117
|
## 前置要求
|
|
118
118
|
|
|
119
|
-
###
|
|
119
|
+
### Python 3.10+(必需)
|
|
120
120
|
|
|
121
121
|
```bash
|
|
122
122
|
# 检查 Python 版本
|
|
123
123
|
python3 --version
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 2. 包管理器(二选一)
|
|
127
124
|
|
|
128
|
-
|
|
125
|
+
# macOS
|
|
126
|
+
brew install python3
|
|
129
127
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
128
|
+
# Linux
|
|
129
|
+
apt-get install python3 python3-pip
|
|
133
130
|
|
|
134
|
-
#
|
|
135
|
-
|
|
131
|
+
# Windows
|
|
132
|
+
# 从 https://www.python.org/downloads/ 下载安装
|
|
136
133
|
```
|
|
137
134
|
|
|
138
|
-
**选项 B:标准 pip(无需额外安装)**
|
|
139
|
-
|
|
140
|
-
如果没有 uv,插件会自动使用 Python 自带的 `pip`。
|
|
141
|
-
|
|
142
135
|
### 2. 启动扫描 API 服务
|
|
143
136
|
|
|
144
137
|
插件需要连接到 skill-scanner-api 服务进行实际的安全扫描。
|
|
@@ -165,14 +158,7 @@ skill-scanner-api
|
|
|
165
158
|
```bash
|
|
166
159
|
# 手动安装依赖
|
|
167
160
|
cd extensions/skills-scanner/skills/skills-scanner
|
|
168
|
-
|
|
169
|
-
# 使用 uv(推荐)
|
|
170
|
-
uv venv .venv --python 3.10
|
|
171
|
-
uv pip install --python .venv/bin/python requests>=2.31.0
|
|
172
|
-
|
|
173
|
-
# 或使用标准 Python
|
|
174
|
-
python3 -m venv .venv
|
|
175
|
-
.venv/bin/python -m pip install requests>=2.31.0
|
|
161
|
+
python3 -m pip install --user "requests>=2.31.0"
|
|
176
162
|
```
|
|
177
163
|
|
|
178
164
|
### API 服务连接失败
|
|
@@ -216,8 +202,7 @@ extensions/skills-scanner/
|
|
|
216
202
|
│ └── types.ts # 类型定义
|
|
217
203
|
└── skills/
|
|
218
204
|
└── skills-scanner/
|
|
219
|
-
|
|
220
|
-
└── .venv/ # Python 虚拟环境(自动创建)
|
|
205
|
+
└── scan.py # Python 扫描脚本
|
|
221
206
|
```
|
|
222
207
|
|
|
223
208
|
## 许可证
|
|
@@ -403,17 +388,13 @@ openclaw skills-scanner clawhub https://clawhub.ai/username/project --json resul
|
|
|
403
388
|
## 依赖要求
|
|
404
389
|
|
|
405
390
|
- Python 3.10+
|
|
406
|
-
- uv(Python 包管理器)
|
|
407
391
|
- skill-scanner-api 服务(需要单独运行)
|
|
408
392
|
|
|
409
393
|
### 安装依赖
|
|
410
394
|
|
|
411
395
|
```bash
|
|
412
|
-
#
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
# Linux
|
|
416
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
396
|
+
# 确保 Python 已安装
|
|
397
|
+
python3 --version
|
|
417
398
|
|
|
418
399
|
# 启动 API 服务
|
|
419
400
|
skill-scanner-api
|
|
@@ -426,8 +407,7 @@ skill-scanner-api
|
|
|
426
407
|
```bash
|
|
427
408
|
# 手动安装依赖
|
|
428
409
|
cd extensions/skills-scanner/skills/skills-scanner
|
|
429
|
-
|
|
430
|
-
uv pip install --python .venv/bin/python requests
|
|
410
|
+
python3 -m pip install --user "requests>=2.31.0"
|
|
431
411
|
```
|
|
432
412
|
|
|
433
413
|
### API 服务连接失败
|
package/index.ts
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
isFirstRun,
|
|
19
19
|
markConfigReviewed,
|
|
20
20
|
} from "./src/state.js";
|
|
21
|
-
import { ensureDeps,
|
|
21
|
+
import { ensureDeps, getPythonCommand, isPythonReady } from "./src/deps.js";
|
|
22
22
|
import { runScan } from "./src/scanner.js";
|
|
23
23
|
import { buildDailyReport } from "./src/report.js";
|
|
24
24
|
import { ensureCronJob } from "./src/cron.js";
|
|
@@ -31,11 +31,12 @@ import { HIGH_RISK_OPERATION_GUARD } from "./src/high-risk-operation-guard.js";
|
|
|
31
31
|
// Constants
|
|
32
32
|
const PLUGIN_ROOT = process.env.OPENCLAW_PLUGIN_ROOT || __dirname;
|
|
33
33
|
const SKILL_DIR = join(PLUGIN_ROOT, "skills", "skills-scanner");
|
|
34
|
-
const VENV_PYTHON = join(SKILL_DIR, ".venv", "bin", "python");
|
|
35
34
|
const SCAN_SCRIPT = join(SKILL_DIR, "scan.py");
|
|
36
35
|
const STATE_DIR = join(os.homedir(), ".openclaw", "skills-scanner");
|
|
37
36
|
const QUARANTINE_DIR = join(STATE_DIR, "quarantine");
|
|
38
37
|
|
|
38
|
+
const PYTHON_CMD = getPythonCommand();
|
|
39
|
+
|
|
39
40
|
export default function register(api: OpenClawPluginApi) {
|
|
40
41
|
const cfg: ScannerConfig =
|
|
41
42
|
api.config?.plugins?.entries?.["skills-scanner"]?.config ?? {};
|
|
@@ -58,7 +59,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
58
59
|
api.logger.info(`[skills-scanner] API URL: ${apiUrl}`);
|
|
59
60
|
api.logger.info(`[skills-scanner] Scan directories: ${scanDirs.join(", ")}`);
|
|
60
61
|
api.logger.info(
|
|
61
|
-
`[skills-scanner] Python dependencies: ${
|
|
62
|
+
`[skills-scanner] Python dependencies: ${isPythonReady(PYTHON_CMD) ? "✅ Ready" : "❌ Not installed"}`
|
|
62
63
|
);
|
|
63
64
|
|
|
64
65
|
// Inject system prompt guidance (can be disabled via config)
|
|
@@ -110,9 +111,9 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
// Install dependencies immediately
|
|
113
|
-
if (!
|
|
114
|
+
if (!isPythonReady(PYTHON_CMD)) {
|
|
114
115
|
api.logger.info("[skills-scanner] Installing Python dependencies...");
|
|
115
|
-
ensureDeps(
|
|
116
|
+
ensureDeps(PYTHON_CMD, api.logger)
|
|
116
117
|
.then((success) => {
|
|
117
118
|
if (success) {
|
|
118
119
|
api.logger.info("[skills-scanner] ✅ Dependencies installed");
|
|
@@ -140,7 +141,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
140
141
|
start: async () => {
|
|
141
142
|
api.logger.info("[skills-scanner] 🚀 Service starting...");
|
|
142
143
|
|
|
143
|
-
const depsReady = await ensureDeps(
|
|
144
|
+
const depsReady = await ensureDeps(PYTHON_CMD, api.logger);
|
|
144
145
|
|
|
145
146
|
if (!depsReady) {
|
|
146
147
|
api.logger.error("[skills-scanner] ❌ Dependencies installation failed");
|
|
@@ -158,7 +159,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
158
159
|
policy,
|
|
159
160
|
persistWatcherAlert,
|
|
160
161
|
api.logger,
|
|
161
|
-
|
|
162
|
+
PYTHON_CMD,
|
|
162
163
|
SCAN_SCRIPT,
|
|
163
164
|
QUARANTINE_DIR
|
|
164
165
|
);
|
|
@@ -192,7 +193,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
192
193
|
policy,
|
|
193
194
|
preInstallScan,
|
|
194
195
|
onUnsafe,
|
|
195
|
-
|
|
196
|
+
PYTHON_CMD,
|
|
196
197
|
SCAN_SCRIPT,
|
|
197
198
|
api.logger
|
|
198
199
|
);
|
|
@@ -261,9 +262,9 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
261
262
|
api.registerGatewayMethod("skillsScanner.scan", async ({ respond, params }: any) => {
|
|
262
263
|
const { path: p, mode = "scan", recursive = false, detailed = false } = params ?? {};
|
|
263
264
|
if (!p) return respond(false, { error: "Missing path parameter" });
|
|
264
|
-
if (!
|
|
265
|
+
if (!isPythonReady(PYTHON_CMD))
|
|
265
266
|
return respond(false, { error: "Python dependencies not ready" });
|
|
266
|
-
const res = await runScan(
|
|
267
|
+
const res = await runScan(PYTHON_CMD, SCAN_SCRIPT, mode === "batch" ? "batch" : "scan", expandPath(p), {
|
|
267
268
|
recursive,
|
|
268
269
|
detailed,
|
|
269
270
|
behavioral,
|
|
@@ -279,7 +280,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
279
280
|
});
|
|
280
281
|
|
|
281
282
|
api.registerGatewayMethod("skillsScanner.report", async ({ respond }: any) => {
|
|
282
|
-
if (!
|
|
283
|
+
if (!isPythonReady(PYTHON_CMD))
|
|
283
284
|
return respond(false, { error: "Python dependencies not ready" });
|
|
284
285
|
if (scanDirs.length === 0) return respond(false, { error: "No scan directories found" });
|
|
285
286
|
const report = await buildDailyReport(
|
|
@@ -289,7 +290,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
289
290
|
useLLM,
|
|
290
291
|
policy,
|
|
291
292
|
api.logger,
|
|
292
|
-
|
|
293
|
+
PYTHON_CMD,
|
|
293
294
|
SCAN_SCRIPT
|
|
294
295
|
);
|
|
295
296
|
respond(true, { report, state: loadState() });
|
|
@@ -306,7 +307,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
306
307
|
.option("--detailed", "显示所有发现")
|
|
307
308
|
.option("--behavioral", "启用行为分析")
|
|
308
309
|
.action(async (p: string, opts: any) => {
|
|
309
|
-
const res = await runScan(
|
|
310
|
+
const res = await runScan(PYTHON_CMD, SCAN_SCRIPT, "scan", expandPath(p), {
|
|
310
311
|
...opts,
|
|
311
312
|
apiUrl,
|
|
312
313
|
useLLM,
|
|
@@ -323,7 +324,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
323
324
|
.option("--detailed", "显示所有发现")
|
|
324
325
|
.option("--behavioral", "启用行为分析")
|
|
325
326
|
.action(async (d: string, opts: any) => {
|
|
326
|
-
const res = await runScan(
|
|
327
|
+
const res = await runScan(PYTHON_CMD, SCAN_SCRIPT, "batch", expandPath(d), {
|
|
327
328
|
...opts,
|
|
328
329
|
apiUrl,
|
|
329
330
|
useLLM,
|
|
@@ -344,7 +345,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
344
345
|
useLLM,
|
|
345
346
|
policy,
|
|
346
347
|
console,
|
|
347
|
-
|
|
348
|
+
PYTHON_CMD,
|
|
348
349
|
SCAN_SCRIPT
|
|
349
350
|
);
|
|
350
351
|
console.log(report);
|
|
@@ -354,7 +355,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
354
355
|
.command("health")
|
|
355
356
|
.description("检查 API 服务健康状态")
|
|
356
357
|
.action(async () => {
|
|
357
|
-
if (!
|
|
358
|
+
if (!isPythonReady(PYTHON_CMD)) {
|
|
358
359
|
console.error("❌ Python 依赖未就绪");
|
|
359
360
|
process.exit(1);
|
|
360
361
|
}
|
|
@@ -364,7 +365,7 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
364
365
|
const { promisify } = await import("node:util");
|
|
365
366
|
const execAsync = promisify(exec);
|
|
366
367
|
|
|
367
|
-
const cmd = `"${
|
|
368
|
+
const cmd = `"${PYTHON_CMD}" "${SCAN_SCRIPT}" --api-url "${apiUrl}" health`;
|
|
368
369
|
const env = { ...process.env };
|
|
369
370
|
delete env.http_proxy;
|
|
370
371
|
delete env.https_proxy;
|
|
@@ -395,3 +396,6 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
395
396
|
|
|
396
397
|
api.logger.info("[skills-scanner] ✅ Plugin registered");
|
|
397
398
|
}
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@pwddd/skills-scanner",
|
|
3
|
-
"version": "3.0.
|
|
2
|
+
"name": "@pwddd/skills-scanner",
|
|
3
|
+
"version": "3.0.8",
|
|
4
4
|
"description": "OpenClaw Skills security scanner plugin - detect malicious code, data exfiltration, and prompt injection",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|