@pwddd/skills-scanner 3.0.17 → 3.0.19
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 +8 -6
- package/index.ts +3 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/commands.ts +15 -11
- package/src/cron.ts +8 -8
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ OpenClaw Skills 安全扫描插件,用于检测 Skills 中的潜在安全威
|
|
|
6
6
|
|
|
7
7
|
- 🔍 **自动扫描**: 监听 Skills 目录,自动扫描新安装的 Skill
|
|
8
8
|
- 🌐 **ClawHub 扫描**: 直接扫描 ClawHub 上的 Skill,无需手动下载
|
|
9
|
-
- 📊
|
|
9
|
+
- 📊 **定时周报**: 每周一自动生成安全扫描报告
|
|
10
10
|
- 🛡️ **多种策略**: 支持 strict/balanced/permissive 三种扫描策略
|
|
11
11
|
- 🤖 **LLM 分析**: 可选的 LLM 语义分析
|
|
12
12
|
- 🔒 **自动隔离**: 检测到不安全的 Skill 自动隔离或删除
|
|
@@ -168,7 +168,7 @@ skill-scanner-api
|
|
|
168
168
|
2. **文件监控**: 监听配置的 Skills 目录
|
|
169
169
|
3. **自动扫描**: 检测到新 Skill 时自动触发扫描
|
|
170
170
|
4. **结果处理**: 根据配置隔离/删除/警告不安全的 Skill
|
|
171
|
-
5.
|
|
171
|
+
5. **定时周报**: 每周一 12:05 自动生成安全报告
|
|
172
172
|
|
|
173
173
|
## 故障排除
|
|
174
174
|
|
|
@@ -225,14 +225,16 @@ Windows 使用反斜杠 `\` 作为路径分隔符,但插件会自动处理。
|
|
|
225
225
|
|
|
226
226
|
### 定时任务未注册
|
|
227
227
|
|
|
228
|
+
定时任务会在插件启动时自动注册。如果需要手动注册:
|
|
229
|
+
|
|
228
230
|
```bash
|
|
229
231
|
# 手动注册定时任务
|
|
230
|
-
/skills-scanner cron
|
|
232
|
+
/skills-scanner cron setup
|
|
231
233
|
|
|
232
234
|
# 或使用 CLI
|
|
233
235
|
openclaw cron add \
|
|
234
|
-
--name "skills-
|
|
235
|
-
--cron "
|
|
236
|
+
--name "skills-weekly-report" \
|
|
237
|
+
--cron "5 12 * * 1" \
|
|
236
238
|
--tz "Asia/Shanghai" \
|
|
237
239
|
--session isolated \
|
|
238
240
|
--message "请执行 /skills-scanner scan --report 并把结果发送到此渠道" \
|
|
@@ -384,7 +386,7 @@ openclaw skills-scanner health
|
|
|
384
386
|
3. **ClawHub 扫描**(聊天命令/CLI):直接扫描 ClawHub 上的 Skill
|
|
385
387
|
4. **CLI 命令扫描**:通过命令行工具扫描
|
|
386
388
|
5. **自动文件监控**:实时监控目录,自动扫描新 Skill
|
|
387
|
-
6.
|
|
389
|
+
6. **定时任务扫描**:每周一 12:05 自动生成周报
|
|
388
390
|
7. **RPC 方法扫描**:供其他插件或程序调用
|
|
389
391
|
8. **AI 主动扫描**:AI 在用户请求安装 Skills 时自动扫描(需启用 `injectSecurityGuidance`)
|
|
390
392
|
|
package/index.ts
CHANGED
|
@@ -170,8 +170,9 @@ export default function register(api: OpenClawPluginApi) {
|
|
|
170
170
|
api.logger.info("[skills-scanner] ⏭️ Pre-install scan disabled");
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
//
|
|
174
|
-
|
|
173
|
+
// Auto-register cron job
|
|
174
|
+
api.logger.info("[skills-scanner] 🕐 Setting up weekly report cron job...");
|
|
175
|
+
await ensureCronJob(api.logger);
|
|
175
176
|
},
|
|
176
177
|
stop: () => {
|
|
177
178
|
api.logger.info("[skills-scanner] 🛑 Service stopping...");
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/src/commands.ts
CHANGED
|
@@ -69,16 +69,7 @@ export function createCommandHandlers(
|
|
|
69
69
|
const recursive = parts.includes("--recursive");
|
|
70
70
|
const isReport = parts.includes("--report");
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
return { text: "⚠️ 请指定扫描路径" };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!existsSync(targetPath)) {
|
|
77
|
-
return { text: `⚠️ 路径不存在: ${targetPath}` };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const isSingleSkill = existsSync(join(targetPath, "SKILL.md"));
|
|
81
|
-
|
|
72
|
+
// Report mode: use configured scanDirs
|
|
82
73
|
if (isReport) {
|
|
83
74
|
if (scanDirs.length === 0) {
|
|
84
75
|
return { text: "⚠️ 未找到可扫描目录,请检查配置" };
|
|
@@ -94,7 +85,20 @@ export function createCommandHandlers(
|
|
|
94
85
|
scanScript
|
|
95
86
|
);
|
|
96
87
|
return { text: report };
|
|
97
|
-
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Regular scan mode: require path
|
|
91
|
+
if (!targetPath) {
|
|
92
|
+
return { text: "⚠️ 请指定扫描路径" };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!existsSync(targetPath)) {
|
|
96
|
+
return { text: `⚠️ 路径不存在: ${targetPath}` };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const isSingleSkill = existsSync(join(targetPath, "SKILL.md"));
|
|
100
|
+
|
|
101
|
+
if (isSingleSkill) {
|
|
98
102
|
const res = await runScan(pythonCmd, scanScript, "scan", targetPath, {
|
|
99
103
|
detailed,
|
|
100
104
|
behavioral: useBehav,
|
package/src/cron.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
import { execSync } from "node:child_process";
|
|
6
6
|
import { loadState, saveState } from "./state.js";
|
|
7
7
|
|
|
8
|
-
const CRON_JOB_NAME = "skills-
|
|
9
|
-
const CRON_SCHEDULE = "
|
|
8
|
+
const CRON_JOB_NAME = "skills-weekly-report";
|
|
9
|
+
const CRON_SCHEDULE = "5 12 * * 1"; // 每周一 12:05
|
|
10
10
|
const CRON_TIMEZONE = "Asia/Shanghai";
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -181,7 +181,7 @@ async function ensureCronJobViaCLI(logger: any): Promise<void> {
|
|
|
181
181
|
`--cron "${CRON_SCHEDULE}"`,
|
|
182
182
|
`--tz "${CRON_TIMEZONE}"`,
|
|
183
183
|
"--session isolated",
|
|
184
|
-
'--message "
|
|
184
|
+
'--message "/skills-scanner scan --report"',
|
|
185
185
|
"--announce",
|
|
186
186
|
"--channel last",
|
|
187
187
|
].join(" ");
|
|
@@ -200,7 +200,7 @@ async function ensureCronJobViaCLI(logger: any): Promise<void> {
|
|
|
200
200
|
saveState({ ...state, cronJobId });
|
|
201
201
|
logger.info(`[skills-scanner] ✅ Job created successfully: ${cronJobId}`);
|
|
202
202
|
logger.info(
|
|
203
|
-
`[skills-scanner] 📅 Schedule:
|
|
203
|
+
`[skills-scanner] 📅 Schedule: Every Monday at 12:05 (${CRON_TIMEZONE})`
|
|
204
204
|
);
|
|
205
205
|
logger.info("[skills-scanner] 📬 Reports will be delivered to the last active channel");
|
|
206
206
|
} else {
|
|
@@ -237,7 +237,7 @@ async function ensureCronJobViaCLI(logger: any): Promise<void> {
|
|
|
237
237
|
logger.info(`[skills-scanner] --tz "${CRON_TIMEZONE}" \\`);
|
|
238
238
|
logger.info("[skills-scanner] --session isolated \\");
|
|
239
239
|
logger.info(
|
|
240
|
-
'[skills-scanner] --message "
|
|
240
|
+
'[skills-scanner] --message "/skills-scanner scan --report" \\'
|
|
241
241
|
);
|
|
242
242
|
logger.info("[skills-scanner] --announce \\");
|
|
243
243
|
logger.info("[skills-scanner] --channel last");
|
|
@@ -259,11 +259,11 @@ export function checkCronJobStatus(logger: any): void {
|
|
|
259
259
|
|
|
260
260
|
if (state.cronJobId) {
|
|
261
261
|
logger.info(`[skills-scanner] ✅ Cron job registered: ${state.cronJobId}`);
|
|
262
|
-
logger.info("[skills-scanner] 📅
|
|
262
|
+
logger.info("[skills-scanner] 📅 Weekly reports will be sent every Monday at 12:05 (Asia/Shanghai)");
|
|
263
263
|
} else {
|
|
264
264
|
logger.info("[skills-scanner] 💡 Cron job not configured yet");
|
|
265
265
|
logger.info("[skills-scanner]");
|
|
266
|
-
logger.info("[skills-scanner] To enable
|
|
266
|
+
logger.info("[skills-scanner] To enable weekly security reports, run:");
|
|
267
267
|
logger.info("[skills-scanner]");
|
|
268
268
|
logger.info("[skills-scanner] npx openclaw cron add \\");
|
|
269
269
|
logger.info(`[skills-scanner] --name "${CRON_JOB_NAME}" \\`);
|
|
@@ -271,7 +271,7 @@ export function checkCronJobStatus(logger: any): void {
|
|
|
271
271
|
logger.info(`[skills-scanner] --tz "${CRON_TIMEZONE}" \\`);
|
|
272
272
|
logger.info("[skills-scanner] --session isolated \\");
|
|
273
273
|
logger.info(
|
|
274
|
-
'[skills-scanner] --message "
|
|
274
|
+
'[skills-scanner] --message "/skills-scanner scan --report" \\'
|
|
275
275
|
);
|
|
276
276
|
logger.info("[skills-scanner] --announce \\");
|
|
277
277
|
logger.info("[skills-scanner] --channel last");
|