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 +45 -1
- package/package.json +1 -1
- package/packages/npm-bloom.json +1 -0
- package/packages/pypi-bloom.json +1 -0
- package/packages/rubygems-bloom.json +1 -0
- package/rules/__init__.py +7 -1
- package/semgrep_loader.py +6 -1
- package/src/tools/scan-mcp.js +186 -0
- package/src/tools/scan-prompt.js +49 -0
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
|
-
|
|
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.
|
|
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",
|