agent-security-scanner-mcp 3.0.0 → 3.2.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.
Files changed (244) hide show
  1. package/README.md +451 -739
  2. package/analyzer.py +51 -7
  3. package/index.js +42 -2697
  4. package/package.json +7 -6
  5. package/regex_fallback.py +66 -0
  6. package/rules/__init__.py +124 -36
  7. package/rules/generic/secrets/gitleaks/adafruit-api-key.yaml +27 -0
  8. package/rules/generic/secrets/gitleaks/adobe-client-id.yaml +27 -0
  9. package/rules/generic/secrets/gitleaks/adobe-client-secret.yaml +27 -0
  10. package/rules/generic/secrets/gitleaks/age-secret-key.yaml +27 -0
  11. package/rules/generic/secrets/gitleaks/airtable-api-key.yaml +27 -0
  12. package/rules/generic/secrets/gitleaks/algolia-api-key.yaml +27 -0
  13. package/rules/generic/secrets/gitleaks/alibaba-access-key-id.yaml +27 -0
  14. package/rules/generic/secrets/gitleaks/alibaba-secret-key.yaml +27 -0
  15. package/rules/generic/secrets/gitleaks/asana-client-id.yaml +27 -0
  16. package/rules/generic/secrets/gitleaks/asana-client-secret.yaml +27 -0
  17. package/rules/generic/secrets/gitleaks/atlassian-api-token.yaml +27 -0
  18. package/rules/generic/secrets/gitleaks/authress-service-client-access-key.yaml +27 -0
  19. package/rules/generic/secrets/gitleaks/aws-access-token.yaml +27 -0
  20. package/rules/generic/secrets/gitleaks/beamer-api-token.yaml +27 -0
  21. package/rules/generic/secrets/gitleaks/bitbucket-client-id.yaml +27 -0
  22. package/rules/generic/secrets/gitleaks/bitbucket-client-secret.yaml +27 -0
  23. package/rules/generic/secrets/gitleaks/bittrex-access-key.yaml +27 -0
  24. package/rules/generic/secrets/gitleaks/bittrex-secret-key.yaml +27 -0
  25. package/rules/generic/secrets/gitleaks/clojars-api-token.yaml +27 -0
  26. package/rules/generic/secrets/gitleaks/cloudflare-api-key.yaml +27 -0
  27. package/rules/generic/secrets/gitleaks/cloudflare-global-api-key.yaml +27 -0
  28. package/rules/generic/secrets/gitleaks/cloudflare-origin-ca-key.yaml +27 -0
  29. package/rules/generic/secrets/gitleaks/codecov-access-token.yaml +27 -0
  30. package/rules/generic/secrets/gitleaks/coinbase-access-token.yaml +27 -0
  31. package/rules/generic/secrets/gitleaks/confluent-access-token.yaml +27 -0
  32. package/rules/generic/secrets/gitleaks/confluent-secret-key.yaml +27 -0
  33. package/rules/generic/secrets/gitleaks/contentful-delivery-api-token.yaml +27 -0
  34. package/rules/generic/secrets/gitleaks/databricks-api-token.yaml +27 -0
  35. package/rules/generic/secrets/gitleaks/datadog-access-token.yaml +27 -0
  36. package/rules/generic/secrets/gitleaks/defined-networking-api-token.yaml +27 -0
  37. package/rules/generic/secrets/gitleaks/digitalocean-access-token.yaml +27 -0
  38. package/rules/generic/secrets/gitleaks/digitalocean-pat.yaml +27 -0
  39. package/rules/generic/secrets/gitleaks/digitalocean-refresh-token.yaml +27 -0
  40. package/rules/generic/secrets/gitleaks/discord-api-token.yaml +27 -0
  41. package/rules/generic/secrets/gitleaks/discord-client-id.yaml +27 -0
  42. package/rules/generic/secrets/gitleaks/discord-client-secret.yaml +27 -0
  43. package/rules/generic/secrets/gitleaks/doppler-api-token.yaml +27 -0
  44. package/rules/generic/secrets/gitleaks/droneci-access-token.yaml +27 -0
  45. package/rules/generic/secrets/gitleaks/dropbox-api-token.yaml +27 -0
  46. package/rules/generic/secrets/gitleaks/dropbox-long-lived-api-token.yaml +27 -0
  47. package/rules/generic/secrets/gitleaks/dropbox-short-lived-api-token.yaml +27 -0
  48. package/rules/generic/secrets/gitleaks/duffel-api-token.yaml +27 -0
  49. package/rules/generic/secrets/gitleaks/dynatrace-api-token.yaml +27 -0
  50. package/rules/generic/secrets/gitleaks/easypost-api-token.yaml +27 -0
  51. package/rules/generic/secrets/gitleaks/easypost-test-api-token.yaml +27 -0
  52. package/rules/generic/secrets/gitleaks/etsy-access-token.yaml +27 -0
  53. package/rules/generic/secrets/gitleaks/facebook-access-token.yaml +27 -0
  54. package/rules/generic/secrets/gitleaks/facebook-page-access-token.yaml +27 -0
  55. package/rules/generic/secrets/gitleaks/facebook-secret.yaml +27 -0
  56. package/rules/generic/secrets/gitleaks/facebook.yaml +27 -0
  57. package/rules/generic/secrets/gitleaks/fastly-api-token.yaml +27 -0
  58. package/rules/generic/secrets/gitleaks/finicity-api-token.yaml +27 -0
  59. package/rules/generic/secrets/gitleaks/finicity-client-secret.yaml +27 -0
  60. package/rules/generic/secrets/gitleaks/finnhub-access-token.yaml +27 -0
  61. package/rules/generic/secrets/gitleaks/flickr-access-token.yaml +27 -0
  62. package/rules/generic/secrets/gitleaks/flutterwave-encryption-key.yaml +27 -0
  63. package/rules/generic/secrets/gitleaks/flutterwave-public-key.yaml +27 -0
  64. package/rules/generic/secrets/gitleaks/flutterwave-secret-key.yaml +27 -0
  65. package/rules/generic/secrets/gitleaks/frameio-api-token.yaml +27 -0
  66. package/rules/generic/secrets/gitleaks/freshbooks-access-token.yaml +27 -0
  67. package/rules/generic/secrets/gitleaks/gcp-api-key.yaml +27 -0
  68. package/rules/generic/secrets/gitleaks/generic-api-key.yaml +76 -0
  69. package/rules/generic/secrets/gitleaks/github-app-token.yaml +27 -0
  70. package/rules/generic/secrets/gitleaks/github-fine-grained-pat.yaml +27 -0
  71. package/rules/generic/secrets/gitleaks/github-oauth.yaml +27 -0
  72. package/rules/generic/secrets/gitleaks/github-pat.yaml +27 -0
  73. package/rules/generic/secrets/gitleaks/github-refresh-token.yaml +27 -0
  74. package/rules/generic/secrets/gitleaks/gitlab-pat.yaml +27 -0
  75. package/rules/generic/secrets/gitleaks/gitlab-ptt.yaml +27 -0
  76. package/rules/generic/secrets/gitleaks/gitlab-rrt.yaml +27 -0
  77. package/rules/generic/secrets/gitleaks/gitter-access-token.yaml +27 -0
  78. package/rules/generic/secrets/gitleaks/gocardless-api-token.yaml +27 -0
  79. package/rules/generic/secrets/gitleaks/grafana-api-key.yaml +27 -0
  80. package/rules/generic/secrets/gitleaks/grafana-cloud-api-token.yaml +27 -0
  81. package/rules/generic/secrets/gitleaks/grafana-service-account-token.yaml +27 -0
  82. package/rules/generic/secrets/gitleaks/harness-api-key.yaml +27 -0
  83. package/rules/generic/secrets/gitleaks/hashicorp-tf-api-token.yaml +27 -0
  84. package/rules/generic/secrets/gitleaks/hashicorp-tf-password.yaml +31 -0
  85. package/rules/generic/secrets/gitleaks/heroku-api-key.yaml +27 -0
  86. package/rules/generic/secrets/gitleaks/hubspot-api-key.yaml +27 -0
  87. package/rules/generic/secrets/gitleaks/huggingface-access-token.yaml +27 -0
  88. package/rules/generic/secrets/gitleaks/huggingface-organization-api-token.yaml +27 -0
  89. package/rules/generic/secrets/gitleaks/infracost-api-token.yaml +27 -0
  90. package/rules/generic/secrets/gitleaks/intercom-api-key.yaml +27 -0
  91. package/rules/generic/secrets/gitleaks/intra42-client-secret.yaml +27 -0
  92. package/rules/generic/secrets/gitleaks/jfrog-api-key.yaml +27 -0
  93. package/rules/generic/secrets/gitleaks/jfrog-identity-token.yaml +27 -0
  94. package/rules/generic/secrets/gitleaks/jwt-base64.yaml +27 -0
  95. package/rules/generic/secrets/gitleaks/jwt.yaml +27 -0
  96. package/rules/generic/secrets/gitleaks/kraken-access-token.yaml +27 -0
  97. package/rules/generic/secrets/gitleaks/kucoin-access-token.yaml +27 -0
  98. package/rules/generic/secrets/gitleaks/kucoin-secret-key.yaml +27 -0
  99. package/rules/generic/secrets/gitleaks/launchdarkly-access-token.yaml +27 -0
  100. package/rules/generic/secrets/gitleaks/linear-api-key.yaml +27 -0
  101. package/rules/generic/secrets/gitleaks/linear-client-secret.yaml +27 -0
  102. package/rules/generic/secrets/gitleaks/linkedin-client-id.yaml +27 -0
  103. package/rules/generic/secrets/gitleaks/linkedin-client-secret.yaml +27 -0
  104. package/rules/generic/secrets/gitleaks/lob-api-key.yaml +27 -0
  105. package/rules/generic/secrets/gitleaks/lob-pub-api-key.yaml +27 -0
  106. package/rules/generic/secrets/gitleaks/mailchimp-api-key.yaml +27 -0
  107. package/rules/generic/secrets/gitleaks/mailgun-private-api-token.yaml +27 -0
  108. package/rules/generic/secrets/gitleaks/mailgun-pub-key.yaml +27 -0
  109. package/rules/generic/secrets/gitleaks/mailgun-signing-key.yaml +27 -0
  110. package/rules/generic/secrets/gitleaks/mapbox-api-token.yaml +27 -0
  111. package/rules/generic/secrets/gitleaks/mattermost-access-token.yaml +27 -0
  112. package/rules/generic/secrets/gitleaks/messagebird-api-token.yaml +27 -0
  113. package/rules/generic/secrets/gitleaks/messagebird-client-id.yaml +27 -0
  114. package/rules/generic/secrets/gitleaks/microsoft-teams-webhook.yaml +27 -0
  115. package/rules/generic/secrets/gitleaks/netlify-access-token.yaml +27 -0
  116. package/rules/generic/secrets/gitleaks/new-relic-browser-api-token.yaml +27 -0
  117. package/rules/generic/secrets/gitleaks/new-relic-insert-key.yaml +27 -0
  118. package/rules/generic/secrets/gitleaks/new-relic-user-api-id.yaml +27 -0
  119. package/rules/generic/secrets/gitleaks/new-relic-user-api-key.yaml +27 -0
  120. package/rules/generic/secrets/gitleaks/npm-access-token.yaml +27 -0
  121. package/rules/generic/secrets/gitleaks/nytimes-access-token.yaml +27 -0
  122. package/rules/generic/secrets/gitleaks/okta-access-token.yaml +27 -0
  123. package/rules/generic/secrets/gitleaks/openai-api-key.yaml +27 -0
  124. package/rules/generic/secrets/gitleaks/plaid-api-token.yaml +27 -0
  125. package/rules/generic/secrets/gitleaks/plaid-client-id.yaml +27 -0
  126. package/rules/generic/secrets/gitleaks/plaid-secret-key.yaml +27 -0
  127. package/rules/generic/secrets/gitleaks/planetscale-api-token.yaml +27 -0
  128. package/rules/generic/secrets/gitleaks/planetscale-oauth-token.yaml +27 -0
  129. package/rules/generic/secrets/gitleaks/planetscale-password.yaml +27 -0
  130. package/rules/generic/secrets/gitleaks/postman-api-token.yaml +27 -0
  131. package/rules/generic/secrets/gitleaks/prefect-api-token.yaml +27 -0
  132. package/rules/generic/secrets/gitleaks/private-key.yaml +27 -0
  133. package/rules/generic/secrets/gitleaks/pulumi-api-token.yaml +27 -0
  134. package/rules/generic/secrets/gitleaks/pypi-upload-token.yaml +27 -0
  135. package/rules/generic/secrets/gitleaks/rapidapi-access-token.yaml +27 -0
  136. package/rules/generic/secrets/gitleaks/readme-api-token.yaml +27 -0
  137. package/rules/generic/secrets/gitleaks/rubygems-api-token.yaml +27 -0
  138. package/rules/generic/secrets/gitleaks/scalingo-api-token.yaml +27 -0
  139. package/rules/generic/secrets/gitleaks/sendbird-access-id.yaml +27 -0
  140. package/rules/generic/secrets/gitleaks/sendbird-access-token.yaml +27 -0
  141. package/rules/generic/secrets/gitleaks/sendgrid-api-token.yaml +27 -0
  142. package/rules/generic/secrets/gitleaks/sendinblue-api-token.yaml +27 -0
  143. package/rules/generic/secrets/gitleaks/sentry-access-token.yaml +27 -0
  144. package/rules/generic/secrets/gitleaks/shippo-api-token.yaml +27 -0
  145. package/rules/generic/secrets/gitleaks/shopify-access-token.yaml +27 -0
  146. package/rules/generic/secrets/gitleaks/shopify-custom-access-token.yaml +27 -0
  147. package/rules/generic/secrets/gitleaks/shopify-private-app-access-token.yaml +27 -0
  148. package/rules/generic/secrets/gitleaks/shopify-shared-secret.yaml +27 -0
  149. package/rules/generic/secrets/gitleaks/sidekiq-secret.yaml +27 -0
  150. package/rules/generic/secrets/gitleaks/sidekiq-sensitive-url.yaml +27 -0
  151. package/rules/generic/secrets/gitleaks/slack-app-token.yaml +27 -0
  152. package/rules/generic/secrets/gitleaks/slack-bot-token.yaml +27 -0
  153. package/rules/generic/secrets/gitleaks/slack-config-access-token.yaml +27 -0
  154. package/rules/generic/secrets/gitleaks/slack-config-refresh-token.yaml +27 -0
  155. package/rules/generic/secrets/gitleaks/slack-legacy-bot-token.yaml +27 -0
  156. package/rules/generic/secrets/gitleaks/slack-legacy-token.yaml +27 -0
  157. package/rules/generic/secrets/gitleaks/slack-legacy-workspace-token.yaml +27 -0
  158. package/rules/generic/secrets/gitleaks/slack-user-token.yaml +27 -0
  159. package/rules/generic/secrets/gitleaks/slack-webhook-url.yaml +27 -0
  160. package/rules/generic/secrets/gitleaks/snyk-api-token.yaml +27 -0
  161. package/rules/generic/secrets/gitleaks/square-access-token.yaml +27 -0
  162. package/rules/generic/secrets/gitleaks/squarespace-access-token.yaml +27 -0
  163. package/rules/generic/secrets/gitleaks/stripe-access-token.yaml +27 -0
  164. package/rules/generic/secrets/gitleaks/sumologic-access-id.yaml +27 -0
  165. package/rules/generic/secrets/gitleaks/sumologic-access-token.yaml +27 -0
  166. package/rules/generic/secrets/gitleaks/telegram-bot-api-token.yaml +27 -0
  167. package/rules/generic/secrets/gitleaks/travisci-access-token.yaml +27 -0
  168. package/rules/generic/secrets/gitleaks/twilio-api-key.yaml +27 -0
  169. package/rules/generic/secrets/gitleaks/twitch-api-token.yaml +27 -0
  170. package/rules/generic/secrets/gitleaks/twitter-access-secret.yaml +27 -0
  171. package/rules/generic/secrets/gitleaks/twitter-access-token.yaml +27 -0
  172. package/rules/generic/secrets/gitleaks/twitter-api-key.yaml +27 -0
  173. package/rules/generic/secrets/gitleaks/twitter-api-secret.yaml +27 -0
  174. package/rules/generic/secrets/gitleaks/twitter-bearer-token.yaml +27 -0
  175. package/rules/generic/secrets/gitleaks/typeform-api-token.yaml +27 -0
  176. package/rules/generic/secrets/gitleaks/vault-batch-token.yaml +27 -0
  177. package/rules/generic/secrets/gitleaks/vault-service-token.yaml +27 -0
  178. package/rules/generic/secrets/gitleaks/yandex-access-token.yaml +27 -0
  179. package/rules/generic/secrets/gitleaks/yandex-api-key.yaml +27 -0
  180. package/rules/generic/secrets/gitleaks/yandex-aws-access-token.yaml +27 -0
  181. package/rules/generic/secrets/gitleaks/zendesk-secret-key.yaml +27 -0
  182. package/rules/generic/secrets/security/detected-amazon-mws-auth-token.yaml +26 -0
  183. package/rules/generic/secrets/security/detected-artifactory-password.yaml +47 -0
  184. package/rules/generic/secrets/security/detected-artifactory-token.yaml +44 -0
  185. package/rules/generic/secrets/security/detected-aws-access-key-id-value.yaml +29 -0
  186. package/rules/generic/secrets/security/detected-aws-account-id.yaml +58 -0
  187. package/rules/generic/secrets/security/detected-aws-appsync-graphql-key.yaml +27 -0
  188. package/rules/generic/secrets/security/detected-aws-secret-access-key.yaml +30 -0
  189. package/rules/generic/secrets/security/detected-aws-session-token.yaml +31 -0
  190. package/rules/generic/secrets/security/detected-bcrypt-hash.yaml +25 -0
  191. package/rules/generic/secrets/security/detected-codeclimate.yaml +27 -0
  192. package/rules/generic/secrets/security/detected-etc-shadow.yaml +27 -0
  193. package/rules/generic/secrets/security/detected-facebook-access-token.yaml +29 -0
  194. package/rules/generic/secrets/security/detected-facebook-oauth.yaml +27 -0
  195. package/rules/generic/secrets/security/detected-generic-api-key.yaml +29 -0
  196. package/rules/generic/secrets/security/detected-generic-secret.yaml +30 -0
  197. package/rules/generic/secrets/security/detected-github-token.yaml +47 -0
  198. package/rules/generic/secrets/security/detected-google-api-key.yaml +29 -0
  199. package/rules/generic/secrets/security/detected-google-cloud-api-key.yaml +27 -0
  200. package/rules/generic/secrets/security/detected-google-gcm-service-account.yaml +27 -0
  201. package/rules/generic/secrets/security/detected-google-oauth-access-token.yaml +26 -0
  202. package/rules/generic/secrets/security/detected-google-oauth.yaml +26 -0
  203. package/rules/generic/secrets/security/detected-heroku-api-key.yaml +27 -0
  204. package/rules/generic/secrets/security/detected-hockeyapp.yaml +27 -0
  205. package/rules/generic/secrets/security/detected-jwt-token.yaml +25 -0
  206. package/rules/generic/secrets/security/detected-kolide-api-key.yaml +25 -0
  207. package/rules/generic/secrets/security/detected-mailchimp-api-key.yaml +26 -0
  208. package/rules/generic/secrets/security/detected-mailgun-api-key.yaml +26 -0
  209. package/rules/generic/secrets/security/detected-npm-registry-auth-token.yaml +33 -0
  210. package/rules/generic/secrets/security/detected-onfido-live-api-token.yaml +20 -0
  211. package/rules/generic/secrets/security/detected-outlook-team.yaml +27 -0
  212. package/rules/generic/secrets/security/detected-paypal-braintree-access-token.yaml +27 -0
  213. package/rules/generic/secrets/security/detected-pgp-private-key-block.yaml +28 -0
  214. package/rules/generic/secrets/security/detected-picatic-api-key.yaml +26 -0
  215. package/rules/generic/secrets/security/detected-private-key.yaml +39 -0
  216. package/rules/generic/secrets/security/detected-sauce-token.yaml +27 -0
  217. package/rules/generic/secrets/security/detected-sendgrid-api-key.yaml +27 -0
  218. package/rules/generic/secrets/security/detected-slack-token.yaml +28 -0
  219. package/rules/generic/secrets/security/detected-slack-webhook.yaml +27 -0
  220. package/rules/generic/secrets/security/detected-snyk-api-key.yaml +26 -0
  221. package/rules/generic/secrets/security/detected-softlayer-api-key.yaml +27 -0
  222. package/rules/generic/secrets/security/detected-sonarqube-docs-api-key.yaml +40 -0
  223. package/rules/generic/secrets/security/detected-square-access-token.yaml +26 -0
  224. package/rules/generic/secrets/security/detected-square-oauth-secret.yaml +27 -0
  225. package/rules/generic/secrets/security/detected-ssh-password.yaml +27 -0
  226. package/rules/generic/secrets/security/detected-stripe-api-key.yaml +26 -0
  227. package/rules/generic/secrets/security/detected-stripe-restricted-api-key.yaml +26 -0
  228. package/rules/generic/secrets/security/detected-telegram-bot-api-key.yaml +30 -0
  229. package/rules/generic/secrets/security/detected-twilio-api-key.yaml +26 -0
  230. package/rules/generic/secrets/security/detected-username-and-password-in-uri.yaml +35 -0
  231. package/rules/generic/secrets/security/google-maps-apikeyleak.yaml +25 -0
  232. package/rules/prompt-injection.security.yaml +4 -0
  233. package/rules/python/flask/security/injection/flask-injection-sinks.yaml +352 -0
  234. package/src/analyzer.py +119 -0
  235. package/src/cli/demo.js +238 -0
  236. package/src/cli/doctor.js +273 -0
  237. package/src/cli/init.js +288 -0
  238. package/src/fix-patterns.js +698 -0
  239. package/src/tools/check-package.js +169 -0
  240. package/src/tools/fix-security.js +115 -0
  241. package/src/tools/scan-packages.js +154 -0
  242. package/src/tools/scan-prompt.js +570 -0
  243. package/src/tools/scan-security.js +117 -0
  244. package/src/utils.js +153 -0
package/analyzer.py CHANGED
@@ -71,6 +71,7 @@ def analyze_file_regex(file_path):
71
71
  try:
72
72
  language = detect_language(file_path)
73
73
  rules = get_rules_for_language(language)
74
+ print(f"[REGEX] Language: {language}, rules loaded: {len(rules)}", file=sys.stderr)
74
75
  with open(file_path, 'r', encoding='utf-8') as f:
75
76
  lines = f.readlines()
76
77
 
@@ -90,13 +91,26 @@ def analyze_file_regex(file_path):
90
91
  'column': match.start() + col_offset,
91
92
  'length': match.end() - match.start(),
92
93
  'severity': rule['severity'],
93
- 'metadata': rule.get('metadata', {})
94
+ 'metadata': rule.get('metadata', {}),
95
+ 'engine': 'regex'
94
96
  })
95
97
  except re.error:
96
98
  continue
97
99
  except Exception as e:
98
100
  return {'error': str(e)}
99
101
 
102
+ # Also apply regex_fallback for broader coverage (C, Rust, C# etc.)
103
+ try:
104
+ from regex_fallback import apply_regex_fallback
105
+ with open(file_path, 'r', errors='replace') as f:
106
+ source = f.read()
107
+ fallback_issues = apply_regex_fallback(source, language, file_path)
108
+ for issue in fallback_issues:
109
+ issue['engine'] = 'regex-fallback'
110
+ issues.extend(fallback_issues)
111
+ except ImportError:
112
+ pass
113
+
100
114
  seen = set()
101
115
  unique = []
102
116
  for issue in issues:
@@ -125,30 +139,51 @@ def analyze_file_ast(file_path):
125
139
 
126
140
  parse_result = parser.parse_file(file_path)
127
141
  if not parse_result.success:
128
- # Fall back to regex if AST parse fails
142
+ print(f"[AST] Parse failed for {file_path}, falling back to regex", file=sys.stderr)
129
143
  return analyze_file_regex(file_path)
130
144
 
145
+ print(f"[AST] Engine active, language: {parse_result.language}, "
146
+ f"rules loaded: {len(rules)}, taint rules: {len(taint_rules)}", file=sys.stderr)
147
+
131
148
  ast = convert_tree(parse_result.tree, parse_result.language, parse_result.source_bytes)
132
149
 
150
+ # Only apply security-relevant rules; exclude non-security and framework-config rules
151
+ # that produce false positives due to broad pattern matching
152
+ SECURITY_CATEGORIES = {'security', 'prompt-injection', 'prompt-injection-content',
153
+ 'prompt-injection-context', 'prompt-injection-delimiter',
154
+ 'prompt-injection-encoded', 'prompt-injection-extraction',
155
+ 'prompt-injection-jailbreak', 'prompt-injection-multi-turn',
156
+ 'prompt-injection-output', 'prompt-injection-privilege', 'unknown'}
157
+ NOISY_RULES = {
158
+ 'avoid_hardcoded_config_DEBUG', 'avoid_hardcoded_config_ENV',
159
+ 'avoid_hardcoded_config_SECRET_KEY', 'avoid_hardcoded_config_TESTING',
160
+ 'flask-wtf-csrf-disabled', 'context-autoescape-off',
161
+ }
133
162
  applicable_rules = [
134
163
  r for r in rules
135
- if parse_result.language in r.languages or 'generic' in r.languages
164
+ if (parse_result.language in r.languages or 'generic' in r.languages)
165
+ and r.metadata.get('category', 'unknown') in SECURITY_CATEGORIES
166
+ and r.id not in NOISY_RULES
136
167
  ]
137
168
 
138
169
  findings = engine.apply_rules(applicable_rules, ast)
139
170
 
140
171
  # Taint analysis
172
+ taint_findings = []
141
173
  if HAS_TAINT_ANALYZER and taint_rules:
142
174
  taint = TaintAnalyzer()
143
175
  applicable_taint = [
144
176
  r for r in taint_rules
145
177
  if parse_result.language in r.languages or 'generic' in r.languages
146
178
  ]
147
- findings.extend(taint.analyze(ast, applicable_taint))
179
+ taint_findings = taint.analyze(ast, applicable_taint)
180
+ print(f"[TAINT] Taint rules: {len(applicable_taint)}, findings: {len(taint_findings)}", file=sys.stderr)
181
+ findings.extend(taint_findings)
148
182
 
149
183
  issues = []
150
184
  for f in findings:
151
185
  length = f.end_column - f.column if f.line == f.end_line else len(f.text)
186
+ is_taint = f in taint_findings
152
187
  issues.append({
153
188
  'ruleId': f.rule_id,
154
189
  'message': f"[{f.rule_name}] {f.message}",
@@ -157,11 +192,20 @@ def analyze_file_ast(file_path):
157
192
  'length': length,
158
193
  'severity': f.severity,
159
194
  'metadata': f.metadata,
195
+ 'engine': 'taint' if is_taint else 'ast',
160
196
  })
161
197
 
162
198
  # Regex fallback for coverage gaps
163
199
  source = parse_result.source_bytes.decode('utf-8', errors='replace')
164
- issues.extend(apply_regex_fallback(source, parse_result.language, file_path))
200
+ regex_fallback_issues = apply_regex_fallback(source, parse_result.language, file_path)
201
+ for issue in regex_fallback_issues:
202
+ issue['engine'] = 'regex-fallback'
203
+ issues.extend(regex_fallback_issues)
204
+
205
+ ast_count = sum(1 for i in issues if i.get('engine') == 'ast')
206
+ taint_count = sum(1 for i in issues if i.get('engine') == 'taint')
207
+ fallback_count = sum(1 for i in issues if i.get('engine') == 'regex-fallback')
208
+ print(f"[AST] Findings: {ast_count} ast + {taint_count} taint + {fallback_count} regex-fallback", file=sys.stderr)
165
209
 
166
210
  seen = set()
167
211
  unique = []
@@ -172,8 +216,8 @@ def analyze_file_ast(file_path):
172
216
  unique.append(issue)
173
217
  return unique
174
218
 
175
- except Exception:
176
- # Fall back to regex on any AST engine error
219
+ except Exception as e:
220
+ print(f"[AST] Error, falling back to regex: {e}", file=sys.stderr)
177
221
  return analyze_file_regex(file_path)
178
222
 
179
223