agent-security-scanner-mcp 3.16.0 → 3.17.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- <img src="./prooflayer-scanner/logo.svg" alt="ProofLayer Logo" width="400"/>
3
+ <img src="./prooflayer-logo.png" alt="ProofLayer Logo" width="400"/>
4
4
 
5
5
  # agent-security-scanner-mcp
6
6
 
@@ -1161,6 +1161,25 @@ All MCP tools support a `verbosity` parameter to minimize context window consump
1161
1161
 
1162
1162
  ## Changelog
1163
1163
 
1164
+ ### v3.17.0 (2026-03-04) - Critical Security Fixes
1165
+
1166
+ **šŸ”“ 6 CRITICAL vulnerabilities fixed | 🟔 4 IMPORTANT issues resolved**
1167
+
1168
+ - **CVE GHSA-345p-7cg4-v4c7**: Fixed MCP SDK cross-client data leak (CVSS 7.1) - updated to @modelcontextprotocol/sdk@1.27.1
1169
+ - **ReDoS Protection**: Added regex timeouts (1s), size limits (500KB), and iteration caps (100) in prompt scanner
1170
+ - **Path Traversal Fix**: Resolved TOCTOU symlink attacks using `realpathSync()` before validation
1171
+ - **Race Condition Fix**: Prevented multiple daemon spawns from concurrent requests
1172
+ - **Promise Rejection Handling**: Wrapped CLI commands in async IIFE to prevent hangs
1173
+ - **Temp File Security**: Fixed symlink attacks with `mkdtempSync()` and restrictive permissions (0600)
1174
+ - **Daemon Orphaning**: Added SIGKILL fallback with 5s timeout for graceful shutdown
1175
+ - **Dependency Updates**: Fixed ajv, hono, and qs vulnerabilities via `npm audit fix`
1176
+
1177
+ **Impact:** npm audit 4→0 vulnerabilities | Security Grade D→B | Test coverage 99.76% (419/420)
1178
+
1179
+ šŸ“„ See [docs/release-notes/SECURITY-FIXES-v3.17.0.md](docs/release-notes/SECURITY-FIXES-v3.17.0.md) for technical details
1180
+
1181
+ ---
1182
+
1164
1183
  ### v3.10.0
1165
1184
  - **`scan_skill` Tool** — 6-layer deep security scanner for OpenClaw skills: prompt injection (59+ rules), AST+taint code analysis, ClawHavoc malware signatures, package supply chain verification, and SHA-256 rug pull detection. Returns A-F grade with hard-fail on ClawHavoc/rug pull/critical findings
1166
1185
  - **ClawHavoc Signature Database** (`rules/clawhavoc.yaml`) — 27 rules, 121 regex patterns across 10 threat categories (reverse shells, crypto miners, info stealers, keyloggers, screen capture, DNS exfiltration, C2 beacons, OpenClaw-specific attacks, campaign patterns, exfil endpoints), mapped to MITRE ATT&CK
package/index.js CHANGED
@@ -238,51 +238,70 @@ server.tool(
238
238
  // See src/cli/init.js, src/cli/doctor.js, src/cli/demo.js
239
239
 
240
240
  // Handle CLI arguments before loading heavy package data
241
+ // Security: Wrap in async IIFE to prevent unhandled promise rejections and race conditions
241
242
  const cliArgs = process.argv.slice(2);
242
- if (cliArgs[0] === 'init') {
243
- runInit(cliArgs.slice(1)).then(() => process.exit(0)).catch((err) => {
244
- console.error(` Error: ${err.message}\n`);
245
- process.exit(1);
246
- });
247
- } else if (cliArgs[0] === 'doctor') {
248
- runDoctor(cliArgs.slice(1)).then(() => process.exit(0)).catch((err) => {
249
- console.error(` Error: ${err.message}\n`);
250
- process.exit(1);
251
- });
252
- } else if (cliArgs[0] === 'demo') {
253
- runDemo(cliArgs.slice(1)).then(() => process.exit(0)).catch((err) => {
254
- console.error(` Error: ${err.message}\n`);
255
- process.exit(1);
256
- });
257
- } else if (cliArgs[0] === 'init-hooks') {
258
- runInitHooks(cliArgs.slice(1)).then(() => process.exit(0)).catch((err) => {
259
- console.error(` Error: ${err.message}\n`);
260
- process.exit(1);
261
- });
262
- } else if (cliArgs[0] === 'report') {
263
- runReport(cliArgs.slice(1)).then(() => process.exit(0)).catch((err) => {
264
- console.error(` Error: ${err.message}\n`);
265
- process.exit(1);
266
- });
267
- } else if (cliArgs[0] === 'scan-prompt') {
268
- // CLI mode: scan-prompt <text> [--verbosity minimal|compact|full]
269
- const text = cliArgs[1];
270
- if (!text) {
271
- console.error('Usage: agent-security-scanner-mcp scan-prompt <text> [--verbosity minimal|compact|full]');
272
- process.exit(1);
273
- }
274
- const verbosityIdx = cliArgs.indexOf('--verbosity');
275
- const verbosity = verbosityIdx !== -1 ? cliArgs[verbosityIdx + 1] : 'compact';
276
243
 
277
- loadPackageLists();
278
- scanAgentPrompt({ prompt_text: text, verbosity }).then(result => {
279
- const output = JSON.parse(result.content[0].text);
280
- console.log(JSON.stringify(output, null, 2));
281
- process.exit(output.action === 'BLOCK' ? 1 : 0);
282
- }).catch(err => {
283
- console.error(JSON.stringify({ error: err.message }));
284
- process.exit(1);
285
- });
244
+ (async () => {
245
+ if (cliArgs[0] === 'init') {
246
+ try {
247
+ await runInit(cliArgs.slice(1));
248
+ process.exit(0);
249
+ } catch (err) {
250
+ console.error(` Error: ${err.message}\n`);
251
+ process.exit(1);
252
+ }
253
+ } else if (cliArgs[0] === 'doctor') {
254
+ try {
255
+ await runDoctor(cliArgs.slice(1));
256
+ process.exit(0);
257
+ } catch (err) {
258
+ console.error(` Error: ${err.message}\n`);
259
+ process.exit(1);
260
+ }
261
+ } else if (cliArgs[0] === 'demo') {
262
+ try {
263
+ await runDemo(cliArgs.slice(1));
264
+ process.exit(0);
265
+ } catch (err) {
266
+ console.error(` Error: ${err.message}\n`);
267
+ process.exit(1);
268
+ }
269
+ } else if (cliArgs[0] === 'init-hooks') {
270
+ try {
271
+ await runInitHooks(cliArgs.slice(1));
272
+ process.exit(0);
273
+ } catch (err) {
274
+ console.error(` Error: ${err.message}\n`);
275
+ process.exit(1);
276
+ }
277
+ } else if (cliArgs[0] === 'report') {
278
+ try {
279
+ await runReport(cliArgs.slice(1));
280
+ process.exit(0);
281
+ } catch (err) {
282
+ console.error(` Error: ${err.message}\n`);
283
+ process.exit(1);
284
+ }
285
+ } else if (cliArgs[0] === 'scan-prompt') {
286
+ // CLI mode: scan-prompt <text> [--verbosity minimal|compact|full]
287
+ const text = cliArgs[1];
288
+ if (!text) {
289
+ console.error('Usage: agent-security-scanner-mcp scan-prompt <text> [--verbosity minimal|compact|full]');
290
+ process.exit(1);
291
+ }
292
+ const verbosityIdx = cliArgs.indexOf('--verbosity');
293
+ const verbosity = verbosityIdx !== -1 ? cliArgs[verbosityIdx + 1] : 'compact';
294
+
295
+ try {
296
+ loadPackageLists();
297
+ const result = await scanAgentPrompt({ prompt_text: text, verbosity });
298
+ const output = JSON.parse(result.content[0].text);
299
+ console.log(JSON.stringify(output, null, 2));
300
+ process.exit(output.action === 'BLOCK' ? 1 : 0);
301
+ } catch (err) {
302
+ console.error(JSON.stringify({ error: err.message }));
303
+ process.exit(1);
304
+ }
286
305
  } else if (cliArgs[0] === 'scan-security') {
287
306
  // CLI mode: scan-security <file> [--verbosity minimal|compact|full] [--format json|sarif]
288
307
  const filePath = cliArgs[1];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-security-scanner-mcp",
3
- "version": "3.16.0",
3
+ "version": "3.17.0",
4
4
  "mcpName": "io.github.sinewaveai/agent-security-scanner-mcp",
5
5
  "description": "Security scanner MCP server for AI coding agents. Prompt injection firewall, package hallucination detection (4.3M+ packages), 1000+ vulnerability rules with AST & taint analysis, auto-fix. For Claude Code, Cursor, Windsurf, Cline, OpenClaw.",
6
6
  "main": "index.js",