agent-security-scanner-mcp 3.15.0 → 3.16.1

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/analyzer.py CHANGED
@@ -12,6 +12,7 @@ import warnings
12
12
 
13
13
  # Suppress regex deprecation warnings for patterns with inline flags
14
14
  warnings.filterwarnings('ignore', category=DeprecationWarning)
15
+ import fnmatch
15
16
  import json
16
17
  import os
17
18
  import re
@@ -70,12 +71,54 @@ def detect_language(file_path):
70
71
  return EXTENSION_MAP.get(ext, 'generic')
71
72
 
72
73
 
74
+ def _matches_path_filter(file_path, rule):
75
+ """Check if file_path matches a rule's paths.include/exclude filter.
76
+
77
+ Returns True if the rule should be applied to this file.
78
+ Rules without paths metadata apply to all files.
79
+ """
80
+ paths = rule.metadata.get('paths') if hasattr(rule, 'metadata') else None
81
+ if not paths or not isinstance(paths, dict):
82
+ return True
83
+
84
+ basename = os.path.basename(file_path)
85
+
86
+ # If include patterns exist, file must match at least one
87
+ include = paths.get('include')
88
+ if include and isinstance(include, list):
89
+ if not any(fnmatch.fnmatch(basename, p) or fnmatch.fnmatch(file_path, p) for p in include):
90
+ return False
91
+
92
+ # If exclude patterns exist, file must NOT match any
93
+ exclude = paths.get('exclude')
94
+ if exclude and isinstance(exclude, list):
95
+ if any(fnmatch.fnmatch(basename, p) or fnmatch.fnmatch(file_path, p) for p in exclude):
96
+ return False
97
+
98
+ return True
99
+
100
+
73
101
  def analyze_file_regex(file_path):
74
102
  """Original regex-based analysis (fallback when tree-sitter unavailable)."""
75
103
  issues = []
76
104
  try:
77
105
  language = detect_language(file_path)
78
- rules = get_rules_for_language(language)
106
+ all_rules = get_rules_for_language(language)
107
+ # Filter out rules whose paths.include/exclude don't match this file
108
+ rules = {}
109
+ basename = os.path.basename(file_path)
110
+ for rid, r in all_rules.items():
111
+ rule_paths = r.get('metadata', {}).get('paths')
112
+ if rule_paths and isinstance(rule_paths, dict):
113
+ include = rule_paths.get('include')
114
+ if include and isinstance(include, list):
115
+ if not any(fnmatch.fnmatch(basename, p) or fnmatch.fnmatch(file_path, p) for p in include):
116
+ continue
117
+ exclude = rule_paths.get('exclude')
118
+ if exclude and isinstance(exclude, list):
119
+ if any(fnmatch.fnmatch(basename, p) or fnmatch.fnmatch(file_path, p) for p in exclude):
120
+ continue
121
+ rules[rid] = r
79
122
  print(f"[REGEX] Language: {language}, rules loaded: {len(rules)}", file=sys.stderr)
80
123
  with open(file_path, 'r', encoding='utf-8') as f:
81
124
  lines = f.readlines()
@@ -170,6 +213,7 @@ def analyze_file_ast(file_path):
170
213
  if (parse_result.language in r.languages or 'generic' in r.languages)
171
214
  and r.metadata.get('category', 'unknown') in SECURITY_CATEGORIES
172
215
  and r.id not in NOISY_RULES
216
+ and _matches_path_filter(file_path, r)
173
217
  ]
174
218
 
175
219
  findings = engine.apply_rules(applicable_rules, ast)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-security-scanner-mcp",
3
- "version": "3.15.0",
3
+ "version": "3.16.1",
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",