agent-security-scanner-mcp 3.10.1 → 3.10.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-security-scanner-mcp",
3
- "version": "3.10.1",
3
+ "version": "3.10.3",
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",
package/src/cli/doctor.js CHANGED
@@ -3,6 +3,7 @@ import { readFileSync, existsSync, writeFileSync, copyFileSync, mkdirSync } from
3
3
  import { dirname, join } from "path";
4
4
  import { homedir, platform } from "os";
5
5
  import { fileURLToPath } from "url";
6
+ import { getDaemonClient } from '../daemon-client.js';
6
7
 
7
8
  // Handle both ESM and CJS bundling (Smithery bundles to CJS)
8
9
  let __dirname;
@@ -158,6 +159,18 @@ export async function runDoctor(args) {
158
159
  console.log(` \u26a0 daemon.py not found (daemon mode unavailable, sync fallback will be used)`);
159
160
  }
160
161
 
162
+ // 3c. Daemon live health check
163
+ if (existsSync(daemonPath) && pythonCmd) {
164
+ try {
165
+ const client = getDaemonClient();
166
+ const health = await client.health();
167
+ console.log(` \u2713 Daemon responding (pid=${health.pid}, cache=${health.cache_size}, uptime=${health.uptime.toFixed(1)}s)`);
168
+ await client.shutdown();
169
+ } catch (e) {
170
+ console.log(` \u26a0 Daemon health check failed: ${e.message}`);
171
+ }
172
+ }
173
+
161
174
  // 4. Python can import yaml (analyzer dependency check)
162
175
  if (pythonCmd && existsSync(analyzerPath)) {
163
176
  const yamlCheck = checkCommand(pythonCmd, ['-c', 'import yaml; print("ok")']);
@@ -13,7 +13,7 @@ try {
13
13
 
14
14
  const DAEMON_SCRIPT = join(__dirname, '..', 'daemon.py');
15
15
  const READY_TIMEOUT = 15000; // 15s to wait for __ready__ signal
16
- const REQUEST_TIMEOUT = 30000; // 30s per request
16
+ const REQUEST_TIMEOUT = 45000; // 45s per request (increased for large files in Codex/complex analysis)
17
17
  const MAX_RESTARTS = 3;
18
18
  const RESTART_WINDOW = 60000; // 60s window for restart counting
19
19
 
@@ -1,6 +1,6 @@
1
1
  // src/tools/scan-security.js
2
2
  import { z } from "zod";
3
- import { existsSync, readFileSync } from "fs";
3
+ import { existsSync, readFileSync, statSync } from "fs";
4
4
  import { dirname } from "path";
5
5
  import { detectLanguage, runAnalyzerAsync, generateFix, toSarif, getEngineMode, extractImports, isTestFile } from '../utils.js';
6
6
  import { deduplicateFindings } from '../dedup.js';
@@ -8,6 +8,8 @@ import { applyContextFilter, detectFrameworks, applyFrameworkAdjustments } from
8
8
  import { loadConfig, shouldExcludeFile, applyConfig } from '../config.js';
9
9
  import { discoverProjectContext } from './project-context.js';
10
10
 
11
+ const MAX_FILE_SIZE = 1024 * 1024; // 1MB - skip files larger than this to avoid timeouts
12
+
11
13
  export const scanSecuritySchema = {
12
14
  file_path: z.string().describe("Path to the file to scan"),
13
15
  output_format: z.enum(['json', 'sarif']).optional().describe("Output format: 'json' (default) or 'sarif' for GitHub/GitLab integration"),
@@ -69,6 +71,26 @@ export async function scanSecurity({ file_path, output_format, verbosity, engine
69
71
  };
70
72
  }
71
73
 
74
+ // Check file size to avoid timeouts on very large files
75
+ try {
76
+ const stats = statSync(file_path);
77
+ if (stats.size > MAX_FILE_SIZE) {
78
+ return {
79
+ content: [{
80
+ type: "text",
81
+ text: JSON.stringify({
82
+ file: file_path,
83
+ message: `File too large (${(stats.size / 1024).toFixed(0)}KB). Skipping to avoid timeout. Max size: ${MAX_FILE_SIZE / 1024}KB.`,
84
+ issues_count: 0,
85
+ skipped: true
86
+ })
87
+ }]
88
+ };
89
+ }
90
+ } catch (err) {
91
+ // If stat fails, continue anyway
92
+ }
93
+
72
94
  // Load project configuration
73
95
  const config = loadConfig(file_path);
74
96
 
package/src/utils.js CHANGED
@@ -86,7 +86,7 @@ export function runAnalyzer(filePath, engine = 'auto') {
86
86
  }
87
87
  const result = execFileSync('python3', args, {
88
88
  encoding: 'utf-8',
89
- timeout: 30000
89
+ timeout: 45000 // Increased to 45s to match daemon timeout
90
90
  });
91
91
  return JSON.parse(result);
92
92
  } catch (error) {