agent-security-scanner-mcp 3.17.2 → 3.19.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/rules/__init__.py CHANGED
@@ -201,16 +201,55 @@ def get_rules():
201
201
  return rules
202
202
 
203
203
 
204
- def get_rules_for_language(language):
205
- """Get rules applicable to a specific language"""
204
+ def get_rules_for_language(language, file_path=None):
205
+ """Get rules applicable to a specific language.
206
+
207
+ Generic rules that declare a specific technology in their metadata are
208
+ only applied when the scanned language or file path indicates that
209
+ technology is relevant. This prevents, e.g., Hugo-specific rules from
210
+ firing on plain JavaScript database code.
211
+ """
206
212
  all_rules = get_rules()
207
213
  applicable_rules = {}
208
214
 
209
215
  language = language.lower()
210
216
 
217
+ # Map technology names to the languages/file-path hints where they apply
218
+ _TECH_LANGUAGES = {
219
+ 'hugo': {'go', 'html', 'toml', 'yaml'},
220
+ 'django': {'python', 'html'},
221
+ 'rails': {'ruby', 'html', 'erb'},
222
+ 'spring': {'java', 'kotlin'},
223
+ 'laravel': {'php'},
224
+ 'angular': {'typescript', 'javascript', 'html'},
225
+ 'react': {'javascript', 'typescript', 'jsx', 'tsx'},
226
+ }
227
+
211
228
  for rule_id, rule in all_rules.items():
212
229
  rule_languages = [lang.lower() for lang in rule.get('languages', ['generic'])]
213
- if language in rule_languages or 'generic' in rule_languages:
230
+
231
+ if language in rule_languages:
232
+ applicable_rules[rule_id] = rule
233
+ continue
234
+
235
+ if 'generic' in rule_languages:
236
+ # Check if this generic rule is scoped to a specific technology
237
+ techs = rule.get('metadata', {}).get('technology')
238
+ if techs and isinstance(techs, list):
239
+ # Only apply if the current language is relevant to the technology
240
+ tech_relevant = False
241
+ for tech in techs:
242
+ tech_lower = tech.lower()
243
+ allowed = _TECH_LANGUAGES.get(tech_lower)
244
+ if allowed and language in allowed:
245
+ tech_relevant = True
246
+ break
247
+ # Also check if the technology name appears in the file path
248
+ if file_path and tech_lower in file_path.lower():
249
+ tech_relevant = True
250
+ break
251
+ if not tech_relevant:
252
+ continue
214
253
  applicable_rules[rule_id] = rule
215
254
 
216
255
  return applicable_rules
@@ -672,8 +672,8 @@ rules:
672
672
  severity: WARNING
673
673
  message: "Potential Base64-encoded prompt injection payload. Encoded content may hide malicious instructions."
674
674
  patterns:
675
- - "(?i)decode\\s+(this\\s+)?base64\\s*:\\s*[A-Za-z0-9+/=]{20,}"
676
- - "(?i)base64\\s*:\\s*[A-Za-z0-9+/=]{40,}"
675
+ - "(?i)decode\\s+(this\\s+)?base64\\s*:\\s*[A-Za-z0-9+/=]{20,200}"
676
+ - "(?i)base64\\s*:\\s*[A-Za-z0-9+/=]{40,200}"
677
677
  - "aWdub3JlIHByZXZpb3Vz"
678
678
  - "c3lzdGVtIHByb21wdA=="
679
679
  - "(?i)execute\\s+(this\\s+)?encoded"
@@ -682,8 +682,8 @@ rules:
682
682
  - "aWdub3JlIGFsbC"
683
683
  - "b3ZlcnJpZGU="
684
684
  - "(?i)base64.{0,20}instructions?.{0,20}follow"
685
- - "[A-Za-z0-9+/]{40,}={0,2}\\s*.{0,20}(?i)(decode|execute|follow|run)"
686
- - "(?i)(decode|run|execute)\\s+.{0,20}[A-Za-z0-9+/]{40,}={0,2}"
685
+ - "[A-Za-z0-9+/]{40,200}={0,2}[^A-Za-z0-9+/=].{0,20}(?:decode|execute|follow|run)"
686
+ - "(?i)(decode|run|execute)\\s+.{0,20}[A-Za-z0-9+/]{40,200}={0,2}"
687
687
  metadata:
688
688
  cwe: "CWE-77"
689
689
  owasp: "LLM01 - Prompt Injection"