@pwddd/skills-scanner 3.0.13 → 3.0.14

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/index.ts CHANGED
@@ -148,6 +148,8 @@ export default function register(api: OpenClawPluginApi) {
148
148
  return;
149
149
  }
150
150
 
151
+ api.logger.info("[skills-scanner] Python dependencies ready (requests installed)");
152
+
151
153
  if (preInstallScan === "on" && scanDirs.length > 0) {
152
154
  api.logger.info(`[skills-scanner] 📁 Starting file monitoring: ${scanDirs.length} directories`);
153
155
  stopWatcher = startWatcher(
@@ -168,14 +170,8 @@ export default function register(api: OpenClawPluginApi) {
168
170
  api.logger.info("[skills-scanner] ⏭️ Pre-install scan disabled");
169
171
  }
170
172
 
171
- // Register cron job (only in Gateway mode)
172
- const isGatewayMode = !!(api as any).runtime;
173
- if (isGatewayMode) {
174
- const runtime = (api as any).runtime;
175
- await ensureCronJob(api.logger, runtime);
176
- }
177
-
178
- api.logger.info("[skills-scanner] ─────────────────────────────────────");
173
+ // Setup cron job via CLI
174
+ await ensureCronJob(api.logger);
179
175
  },
180
176
  stop: () => {
181
177
  api.logger.info("[skills-scanner] 🛑 Service stopping...");
@@ -2,7 +2,7 @@
2
2
  "id": "skills-scanner",
3
3
  "name": "Skills Scanner",
4
4
  "description": "Security scanner for OpenClaw Skills to detect potential threats",
5
- "version": "3.0.13",
5
+ "version": "3.0.14",
6
6
  "author": "pwddd",
7
7
  "skills": ["./skills"],
8
8
  "configSchema": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pwddd/skills-scanner",
3
- "version": "3.0.13",
3
+ "version": "3.0.14",
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",
package/src/cron.ts CHANGED
@@ -57,68 +57,26 @@ function getOpenClawCommand(): string {
57
57
  }
58
58
 
59
59
  /**
60
- * Create cron job via Gateway API (most reliable)
60
+ * Create cron job via CLI
61
61
  */
62
- async function ensureCronJobViaAPI(runtime: any, logger: any): Promise<boolean> {
63
- if (!runtime?.cron) {
64
- logger.debug("[skills-scanner] Cron API not available");
65
- return false;
66
- }
62
+ async function ensureCronJobViaCLI(logger: any): Promise<void> {
63
+ const openclawCmd = getOpenClawCommand();
64
+ logger.info(`[skills-scanner] Using CLI command: ${openclawCmd}`);
67
65
 
66
+ // Test if command is available
68
67
  try {
69
- const state = loadState() as any;
70
-
71
- // Check if job already exists
72
- const jobs = await runtime.cron.list({ includeDisabled: true });
73
- const existing = jobs.find((j: any) => j.name === CRON_JOB_NAME);
74
-
75
- if (existing) {
76
- logger.info(`[skills-scanner] ✅ Job already exists: ${existing.id}`);
77
- if (state.cronJobId !== existing.id) {
78
- saveState({ ...state, cronJobId: existing.id });
79
- }
80
- return true;
81
- }
82
-
83
- // Create new job
84
- logger.info("[skills-scanner] 📝 Creating cron job via API...");
85
- const job = await runtime.cron.add({
86
- name: CRON_JOB_NAME,
87
- enabled: true,
88
- schedule: {
89
- kind: "cron",
90
- expr: CRON_SCHEDULE,
91
- tz: CRON_TIMEZONE
92
- },
93
- payload: {
94
- kind: "agentTurn",
95
- message: "Please run /skills-scanner scan --report and send results to this channel"
96
- },
97
- delivery: {
98
- mode: "announce",
99
- channel: "last"
100
- }
68
+ const testResult = execSync(`${openclawCmd} --version`, {
69
+ encoding: "utf-8",
70
+ timeout: 5000,
71
+ stdio: "pipe"
101
72
  });
102
-
103
- saveState({ ...state, cronJobId: job.id });
104
- logger.info(`[skills-scanner] Job created successfully via API: ${job.id}`);
105
- logger.info(
106
- `[skills-scanner] 📅 Schedule: Daily at ${CRON_SCHEDULE.split(" ")[1]}:${CRON_SCHEDULE.split(" ")[0]} (${CRON_TIMEZONE})`
107
- );
108
- logger.info("[skills-scanner] 📬 Reports will be delivered to the last active channel");
109
- return true;
110
- } catch (err: any) {
111
- logger.warn(`[skills-scanner] API creation failed: ${err.message}`);
112
- return false;
73
+ logger.info(`[skills-scanner] Command test successful: ${testResult.trim()}`);
74
+ } catch (testErr: any) {
75
+ logger.error(`[skills-scanner] Command not available: ${testErr.message}`);
76
+ logger.info(`[skills-scanner] 💡 Please ensure OpenClaw is installed and accessible`);
77
+ logger.info(`[skills-scanner] 💡 Try running: ${openclawCmd} --version`);
78
+ return;
113
79
  }
114
- }
115
-
116
- /**
117
- * Create cron job via CLI (fallback)
118
- */
119
- async function ensureCronJobViaCLI(logger: any): Promise<void> {
120
- const openclawCmd = getOpenClawCommand();
121
- logger.info(`[skills-scanner] Using CLI command: ${openclawCmd}`);
122
80
 
123
81
  const state = loadState() as any;
124
82
 
@@ -228,6 +186,8 @@ async function ensureCronJobViaCLI(logger: any): Promise<void> {
228
186
  "--channel last",
229
187
  ].join(" ");
230
188
 
189
+ logger.info(`[skills-scanner] Executing: ${cronCmd}`);
190
+
231
191
  const result = execSync(cronCmd, { encoding: "utf-8", timeout: 10000 });
232
192
 
233
193
  const jobIdMatch =
@@ -250,7 +210,15 @@ async function ensureCronJobViaCLI(logger: any): Promise<void> {
250
210
  }
251
211
  } catch (err: any) {
252
212
  logger.warn("[skills-scanner] ⚠️ Auto-registration failed");
253
- logger.debug(`[skills-scanner] Error details: ${err.message}`);
213
+ logger.warn(`[skills-scanner] Error: ${err.message || err}`);
214
+
215
+ // Log stderr if available
216
+ if (err.stderr) {
217
+ logger.warn(`[skills-scanner] stderr: ${err.stderr}`);
218
+ }
219
+ if (err.stdout) {
220
+ logger.warn(`[skills-scanner] stdout: ${err.stdout}`);
221
+ }
254
222
 
255
223
  if (err.message.includes("permission") || err.message.includes("EACCES")) {
256
224
  logger.error("[skills-scanner] ❌ Permission denied, please run with admin privileges");
@@ -259,6 +227,7 @@ async function ensureCronJobViaCLI(logger: any): Promise<void> {
259
227
  err.message.includes("ENOENT")
260
228
  ) {
261
229
  logger.error(`[skills-scanner] ❌ ${openclawCmd} command not found, please check installation`);
230
+ logger.info(`[skills-scanner] 💡 Current PATH: ${process.env.PATH}`);
262
231
  } else {
263
232
  logger.info("[skills-scanner] 💡 Please manually register cron job:");
264
233
  logger.info("[skills-scanner]");
@@ -281,22 +250,11 @@ async function ensureCronJobViaCLI(logger: any): Promise<void> {
281
250
  }
282
251
 
283
252
  /**
284
- * Ensure cron job exists (tries API first, falls back to CLI)
253
+ * Ensure cron job exists via CLI
285
254
  */
286
- export async function ensureCronJob(logger: any, runtime?: any): Promise<void> {
255
+ export async function ensureCronJob(logger: any): Promise<void> {
287
256
  logger.info("[skills-scanner] ─────────────────────────────────────");
288
257
  logger.info("[skills-scanner] 🕐 Checking cron job...");
289
258
 
290
- // Try API first (most reliable)
291
- if (runtime) {
292
- const success = await ensureCronJobViaAPI(runtime, logger);
293
- if (success) {
294
- logger.info("[skills-scanner] ✅ Cron job configured via API");
295
- return;
296
- }
297
- logger.info("[skills-scanner] Falling back to CLI method...");
298
- }
299
-
300
- // Fallback to CLI
301
259
  await ensureCronJobViaCLI(logger);
302
260
  }