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
@@ -0,0 +1,698 @@
1
+ // Helper: return correct env var access syntax per language
2
+ export function envVarReplacement(envName, lang) {
3
+ switch(lang) {
4
+ case 'python': return `os.environ.get("${envName}")`;
5
+ case 'go': return `os.Getenv("${envName}")`;
6
+ case 'java': return `System.getenv("${envName}")`;
7
+ case 'php': return `getenv('${envName}')`;
8
+ case 'ruby': return `ENV["${envName}"]`;
9
+ case 'csharp': return `Environment.GetEnvironmentVariable("${envName}")`;
10
+ case 'rust': return `std::env::var("${envName}").unwrap_or_default()`;
11
+ case 'c': case 'cpp': return `getenv("${envName}")`;
12
+ default: return `process.env.${envName}`;
13
+ }
14
+ }
15
+
16
+ // Security fix templates - comprehensive coverage for 165+ rules
17
+ export const FIX_TEMPLATES = {
18
+ // ===========================================
19
+ // SQL INJECTION
20
+ // ===========================================
21
+ "sql-injection": {
22
+ description: "Use parameterized queries instead of string concatenation",
23
+ fix: (line) => line.replace(/["']([^"']*)\s*["']\s*\+\s*(\w+)/, '"$1?", [$2]')
24
+ },
25
+ "nosql-injection": {
26
+ description: "Sanitize MongoDB query inputs",
27
+ fix: (line) => line.replace(/\{\s*(\w+)\s*:\s*(\w+)\s*\}/, '{ $1: sanitize($2) }')
28
+ },
29
+ "raw-query": {
30
+ description: "Use parameterized queries instead of raw SQL",
31
+ fix: (line) => line.replace(/\.query\s*\(\s*["'`]/, '.query("SELECT * FROM table WHERE id = ?", [')
32
+ },
33
+
34
+ // ===========================================
35
+ // XSS (Cross-Site Scripting)
36
+ // ===========================================
37
+ "innerhtml": {
38
+ description: "Use textContent or DOMPurify.sanitize()",
39
+ fix: (line) => line.replace(/\.innerHTML\s*=/, '.textContent =')
40
+ },
41
+ "outerhtml": {
42
+ description: "Use textContent or DOMPurify.sanitize()",
43
+ fix: (line) => line.replace(/\.outerHTML\s*=/, '.textContent =')
44
+ },
45
+ "document-write": {
46
+ description: "Use DOM methods instead of document.write()",
47
+ fix: (line) => line.replace(/document\.write(ln)?\s*\(/, 'document.body.appendChild(document.createTextNode(')
48
+ },
49
+ "insertadjacenthtml": {
50
+ description: "Use insertAdjacentText or sanitize input",
51
+ fix: (line) => line.replace(/\.insertAdjacentHTML\s*\(/, '.insertAdjacentText(')
52
+ },
53
+ "dangerouslysetinnerhtml": {
54
+ description: "Sanitize content with DOMPurify before using dangerouslySetInnerHTML",
55
+ fix: (line) => line.replace(/dangerouslySetInnerHTML\s*=\s*\{\s*\{\s*__html\s*:\s*(\w+)/, 'dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize($1)')
56
+ },
57
+ "xss-response-writer": {
58
+ description: "Escape HTML output before writing to response",
59
+ fix: (line) => line.replace(/\.Write\s*\(\s*(\w+)/, '.Write(html.EscapeString($1)')
60
+ },
61
+
62
+ // ===========================================
63
+ // COMMAND INJECTION
64
+ // ===========================================
65
+ "child-process-exec": {
66
+ description: "Use execFile() or spawn() with shell: false",
67
+ fix: (line) => line.replace(/\bexec\s*\(/, 'execFile(')
68
+ },
69
+ "spawn-shell": {
70
+ description: "Use spawn with shell: false",
71
+ fix: (line) => line.replace(/shell\s*:\s*true/i, 'shell: false')
72
+ },
73
+ "dangerous-subprocess": {
74
+ description: "Use subprocess.run with list arguments",
75
+ fix: (line) => line.replace(/subprocess\.(call|run|Popen)\s*\(\s*["'](.+?)["']\s*,\s*shell\s*=\s*True/, 'subprocess.$1(["$2".split()], shell=False')
76
+ },
77
+ "dangerous-system-call": {
78
+ description: "Use subprocess.run instead of os.system",
79
+ fix: (line) => line.replace(/os\.system\s*\(/, 'subprocess.run([')
80
+ },
81
+ "command-injection-exec": {
82
+ description: "Use exec.Command with separate arguments",
83
+ fix: (line) => line.replace(/exec\.Command\s*\(\s*["'](\w+)\s+/, 'exec.Command("$1", ')
84
+ },
85
+ "runtime-exec": {
86
+ description: "Use ProcessBuilder with separate arguments",
87
+ fix: (line) => line.replace(/Runtime\.getRuntime\(\)\.exec\s*\(/, 'new ProcessBuilder(')
88
+ },
89
+ "process-builder": {
90
+ description: "Validate and sanitize command arguments",
91
+ fix: (line) => line.replace(/new ProcessBuilder\s*\(\s*(.+?)\s*\)/, 'new ProcessBuilder(validateArgs($1))')
92
+ },
93
+
94
+ // ===========================================
95
+ // HARDCODED SECRETS & CREDENTIALS
96
+ // ===========================================
97
+ "hardcoded": {
98
+ description: "Use environment variables",
99
+ fix: (line, lang) => line.replace(/=\s*["'][^"']+["']/, `= ${envVarReplacement("SECRET", lang)}`)
100
+ },
101
+ "api-key": {
102
+ description: "Use environment variables for API keys",
103
+ fix: (line, lang) => line.replace(/=\s*["'][^"']+["']/, `= ${envVarReplacement("API_KEY", lang)}`)
104
+ },
105
+ "password": {
106
+ description: "Use environment variables for passwords",
107
+ fix: (line, lang) => line.replace(/=\s*["'][^"']+["']/, `= ${envVarReplacement("PASSWORD", lang)}`)
108
+ },
109
+ "secret-key": {
110
+ description: "Use environment variables for secret keys",
111
+ fix: (line, lang) => line.replace(/=\s*["'][^"']+["']/, `= ${envVarReplacement("SECRET_KEY", lang)}`)
112
+ },
113
+ "aws-access": {
114
+ description: "Use AWS credentials from environment or IAM roles",
115
+ fix: (line, lang) => line.replace(/=\s*["']AKIA[^"']+["']/, `= ${envVarReplacement("AWS_ACCESS_KEY_ID", lang)}`)
116
+ },
117
+ "aws-secret": {
118
+ description: "Use AWS credentials from environment or IAM roles",
119
+ fix: (line, lang) => line.replace(/=\s*["'][^"']{40}["']/, `= ${envVarReplacement("AWS_SECRET_ACCESS_KEY", lang)}`)
120
+ },
121
+ "stripe": {
122
+ description: "Use environment variables for Stripe keys",
123
+ fix: (line, lang) => line.replace(/=\s*["']sk_(live|test)_[^"']+["']/, `= ${envVarReplacement("STRIPE_SECRET_KEY", lang)}`)
124
+ },
125
+ "github": {
126
+ description: "Use environment variables for GitHub tokens",
127
+ fix: (line, lang) => line.replace(/=\s*["'](ghp_|github_pat_)[^"']+["']/, `= ${envVarReplacement("GITHUB_TOKEN", lang)}`)
128
+ },
129
+ "openai": {
130
+ description: "Use environment variables for OpenAI keys",
131
+ fix: (line, lang) => line.replace(/=\s*["']sk-[^"']+["']/, `= ${envVarReplacement("OPENAI_API_KEY", lang)}`)
132
+ },
133
+ "slack": {
134
+ description: "Use environment variables for Slack tokens",
135
+ fix: (line, lang) => line.replace(/=\s*["']xox[baprs]-[^"']+["']/, `= ${envVarReplacement("SLACK_TOKEN", lang)}`)
136
+ },
137
+ "jwt-token": {
138
+ description: "Use environment variables for JWT secrets",
139
+ fix: (line, lang) => line.replace(/=\s*["'][^"']+["']/, `= ${envVarReplacement("JWT_SECRET", lang)}`)
140
+ },
141
+ "private-key": {
142
+ description: "Load private keys from secure file or vault",
143
+ fix: (line, lang) => {
144
+ if (lang === 'python') return line.replace(/=\s*["']-----BEGIN[^"']+["']/, `= load_key_from_file(${envVarReplacement("PRIVATE_KEY_PATH", lang)})`);
145
+ if (lang === 'go' || lang === 'java' || lang === 'csharp' || lang === 'rust' || lang === 'c' || lang === 'cpp')
146
+ return line.replace(/=\s*["']-----BEGIN[^"']+["']/, `= ${envVarReplacement("PRIVATE_KEY_PATH", lang)}`);
147
+ return line.replace(/=\s*["']-----BEGIN[^"']+["']/, '= fs.readFileSync(process.env.PRIVATE_KEY_PATH)');
148
+ }
149
+ },
150
+ "database-url": {
151
+ description: "Use environment variables for database URLs",
152
+ fix: (line, lang) => line.replace(/=\s*["'][^"']+["']/, `= ${envVarReplacement("DATABASE_URL", lang)}`)
153
+ },
154
+
155
+ // ===========================================
156
+ // WEAK CRYPTOGRAPHY
157
+ // ===========================================
158
+ "md5": {
159
+ description: "Use SHA-256 or stronger",
160
+ fix: (line) => line.replace(/md5/gi, 'sha256')
161
+ },
162
+ "sha1": {
163
+ description: "Use SHA-256 or stronger",
164
+ fix: (line) => line.replace(/sha1/gi, 'sha256')
165
+ },
166
+ "des": {
167
+ description: "Use AES instead of DES",
168
+ fix: (line) => line.replace(/DES/g, 'AES').replace(/des/g, 'aes')
169
+ },
170
+ "ecb-mode": {
171
+ description: "Use CBC or GCM mode instead of ECB",
172
+ fix: (line) => line.replace(/ECB/g, 'GCM').replace(/ecb/g, 'gcm')
173
+ },
174
+ "weak-cipher": {
175
+ description: "Use AES-256-GCM or ChaCha20-Poly1305",
176
+ fix: (line) => line.replace(/(DES|RC4|Blowfish)/gi, 'AES')
177
+ },
178
+ "insecure-random": {
179
+ description: "Use cryptographically secure random",
180
+ fix: (line, lang) => {
181
+ if (lang === 'python') return line.replace(/random\.(random|randint|choice|randrange)\s*\(/, 'secrets.token_hex(');
182
+ if (lang === 'go') return line.replace(/math\/rand/, 'crypto/rand');
183
+ if (lang === 'java') return line.replace(/new Random\(\)/, 'SecureRandom.getInstanceStrong()');
184
+ return line.replace(/Math\.random\s*\(\)/, 'crypto.randomUUID()');
185
+ }
186
+ },
187
+ "weak-rsa": {
188
+ description: "Use RSA key size of 2048 bits or more",
189
+ fix: (line) => line.replace(/\b(512|1024)\b/, '2048')
190
+ },
191
+ "weak-tls": {
192
+ description: "Use TLS 1.2 or higher",
193
+ fix: (line) => line.replace(/TLS1[01]|SSLv[23]/gi, 'TLS12')
194
+ },
195
+
196
+ // ===========================================
197
+ // INSECURE DESERIALIZATION
198
+ // ===========================================
199
+ "pickle": {
200
+ description: "Use JSON instead of pickle",
201
+ fix: (line) => line.replace(/pickle\.(load|loads)\s*\(/, 'json.$1(')
202
+ },
203
+ "yaml-load": {
204
+ description: "Use yaml.safe_load()",
205
+ fix: (line) => line.replace(/yaml\.load\s*\(/, 'yaml.safe_load(')
206
+ },
207
+ "marshal": {
208
+ description: "Use JSON instead of marshal",
209
+ fix: (line) => line.replace(/marshal\.(load|loads)\s*\(/, 'json.$1(')
210
+ },
211
+ "shelve": {
212
+ description: "Use JSON or SQLite instead of shelve",
213
+ fix: (line) => line.replace(/shelve\.open\s*\(/, 'json.load(open(')
214
+ },
215
+ "node-serialize": {
216
+ description: "Use JSON.parse instead of node-serialize",
217
+ fix: (line) => line.replace(/serialize\.unserialize\s*\(/, 'JSON.parse(')
218
+ },
219
+ "object-inputstream": {
220
+ description: "Use JSON or validated deserialization",
221
+ fix: (line) => line.replace(/new ObjectInputStream\s*\(/, 'new JsonReader(')
222
+ },
223
+ "xstream": {
224
+ description: "Configure XStream security or use JSON",
225
+ fix: (line) => line.replace(/xstream\.fromXML\s*\(/, 'new ObjectMapper().readValue(')
226
+ },
227
+ "gob-decode": {
228
+ description: "Use JSON instead of gob for untrusted data",
229
+ fix: (line) => line.replace(/gob\.NewDecoder/, 'json.NewDecoder')
230
+ },
231
+
232
+ // ===========================================
233
+ // SSL/TLS ISSUES
234
+ // ===========================================
235
+ "verify": {
236
+ description: "Enable SSL verification",
237
+ fix: (line) => line.replace(/verify\s*=\s*False/i, 'verify=True')
238
+ },
239
+ "insecure-skip-verify": {
240
+ description: "Enable certificate verification",
241
+ fix: (line) => line.replace(/InsecureSkipVerify\s*:\s*true/, 'InsecureSkipVerify: false')
242
+ },
243
+ "reject-unauthorized": {
244
+ description: "Enable certificate verification",
245
+ fix: (line) => line.replace(/rejectUnauthorized\s*:\s*false/, 'rejectUnauthorized: true')
246
+ },
247
+ "trust-all": {
248
+ description: "Remove trust-all certificate configuration",
249
+ fix: (line) => '// TODO: Remove trust-all certificates - ' + line
250
+ },
251
+ "ssl-verify-disabled": {
252
+ description: "Enable SSL verification",
253
+ fix: (line) => line.replace(/verify\s*=\s*False/, 'verify=True')
254
+ },
255
+
256
+ // ===========================================
257
+ // PATH TRAVERSAL
258
+ // ===========================================
259
+ "path-traversal": {
260
+ description: "Sanitize file paths and use basename",
261
+ fix: (line, lang) => {
262
+ if (lang === 'python') return line.replace(/open\s*\(\s*(\w+)/, 'open(os.path.basename($1)');
263
+ if (lang === 'go') return line.replace(/os\.Open\s*\(\s*(\w+)/, 'os.Open(filepath.Base($1)');
264
+ if (lang === 'java') return line.replace(/new File\s*\(\s*(\w+)/, 'new File(new File($1).getName()');
265
+ return line.replace(/readFileSync\s*\(\s*(\w+)/, 'readFileSync(path.basename($1)');
266
+ }
267
+ },
268
+
269
+ // ===========================================
270
+ // SSRF (Server-Side Request Forgery)
271
+ // ===========================================
272
+ "ssrf": {
273
+ description: "Validate and whitelist URLs before making requests",
274
+ fix: (line) => line.replace(/(axios|fetch|requests|http)\.(get|post|request)\s*\(\s*(\w+)/, '$1.$2(validateUrl($3)')
275
+ },
276
+
277
+ // ===========================================
278
+ // EVAL AND CODE INJECTION
279
+ // ===========================================
280
+ "eval": {
281
+ description: "Avoid eval() - use safer alternatives",
282
+ fix: (line) => '// SECURITY: Remove eval() - ' + line
283
+ },
284
+ "exec-detected": {
285
+ description: "Avoid exec() - use safer alternatives",
286
+ fix: (line) => '# SECURITY: Remove exec() - ' + line
287
+ },
288
+ "compile-detected": {
289
+ description: "Avoid compile() with untrusted input",
290
+ fix: (line) => '# SECURITY: Review compile() usage - ' + line
291
+ },
292
+ "function-constructor": {
293
+ description: "Avoid Function constructor - use safer alternatives",
294
+ fix: (line) => '// SECURITY: Remove Function() constructor - ' + line
295
+ },
296
+ "settimeout-string": {
297
+ description: "Use function reference instead of string",
298
+ fix: (line) => line.replace(/setTimeout\s*\(\s*["'](.+?)["']/, 'setTimeout(() => { $1 }')
299
+ },
300
+
301
+ // ===========================================
302
+ // OPEN REDIRECT
303
+ // ===========================================
304
+ "open-redirect": {
305
+ description: "Validate redirect URLs against whitelist",
306
+ fix: (line) => line.replace(/redirect\s*\(\s*(\w+)/, 'redirect(validateRedirectUrl($1)')
307
+ },
308
+
309
+ // ===========================================
310
+ // CORS
311
+ // ===========================================
312
+ "cors-wildcard": {
313
+ description: "Specify allowed origins instead of wildcard",
314
+ fix: (line) => line.replace(/['"]\*['"]/, '"https://yourdomain.com"')
315
+ },
316
+
317
+ // ===========================================
318
+ // CSRF
319
+ // ===========================================
320
+ "csrf": {
321
+ description: "Enable CSRF protection",
322
+ fix: (line) => line.replace(/csrf\s*:\s*false/i, 'csrf: true').replace(/@csrf_exempt/, '# @csrf_exempt // TODO: Add CSRF protection')
323
+ },
324
+
325
+ // ===========================================
326
+ // DEBUG MODE
327
+ // ===========================================
328
+ "debug": {
329
+ description: "Disable debug mode in production",
330
+ fix: (line) => line.replace(/debug\s*=\s*True/i, 'debug=os.environ.get("DEBUG", "False").lower() == "true"')
331
+ },
332
+
333
+ // ===========================================
334
+ // JWT ISSUES
335
+ // ===========================================
336
+ "jwt-none": {
337
+ description: "Specify a secure algorithm for JWT",
338
+ fix: (line) => line.replace(/algorithm\s*[=:]\s*["']none["']/i, 'algorithm: "HS256"')
339
+ },
340
+ "jwt-decode-without-verify": {
341
+ description: "Enable JWT signature verification",
342
+ fix: (line) => line.replace(/verify\s*=\s*False/, 'verify=True')
343
+ },
344
+
345
+ // ===========================================
346
+ // XXE (XML External Entities)
347
+ // ===========================================
348
+ "xxe": {
349
+ description: "Disable external entities in XML parser",
350
+ fix: (line, lang) => {
351
+ if (lang === 'python') return line.replace(/etree\.parse\s*\(/, 'etree.parse(parser=etree.XMLParser(resolve_entities=False), ');
352
+ if (lang === 'java') return '// TODO: Disable external entities - ' + line;
353
+ return line;
354
+ }
355
+ },
356
+ "lxml": {
357
+ description: "Disable external entities in lxml",
358
+ fix: (line) => line.replace(/etree\.(parse|fromstring)\s*\(/, 'etree.$1(parser=etree.XMLParser(resolve_entities=False, no_network=True), ')
359
+ },
360
+
361
+ // ===========================================
362
+ // LDAP INJECTION
363
+ // ===========================================
364
+ "ldap-injection": {
365
+ description: "Escape LDAP special characters in user input",
366
+ fix: (line) => line.replace(/filter\s*=\s*["']([^"']*)\s*["']\s*\+\s*(\w+)/, 'filter = "$1" + escapeLdap($2)')
367
+ },
368
+
369
+ // ===========================================
370
+ // XPATH INJECTION
371
+ // ===========================================
372
+ "xpath-injection": {
373
+ description: "Use parameterized XPath queries",
374
+ fix: (line) => line.replace(/xpath\s*\(\s*["']([^"']*)\s*["']\s*\+\s*(\w+)/, 'xpath("$1?", [$2]')
375
+ },
376
+
377
+ // ===========================================
378
+ // TEMPLATE INJECTION
379
+ // ===========================================
380
+ "template-injection": {
381
+ description: "Avoid user input in template strings",
382
+ fix: (line) => '// TODO: Sanitize template input - ' + line
383
+ },
384
+ "jinja2-autoescape": {
385
+ description: "Enable autoescape in Jinja2 templates",
386
+ fix: (line) => line.replace(/autoescape\s*=\s*False/, 'autoescape=True')
387
+ },
388
+
389
+ // ===========================================
390
+ // LOGGING SENSITIVE DATA
391
+ // ===========================================
392
+ "logging-sensitive": {
393
+ description: "Remove sensitive data from logs",
394
+ fix: (line) => line.replace(/(password|secret|token|key|credential)/gi, '[REDACTED]')
395
+ },
396
+
397
+ // ===========================================
398
+ // REGEX DOS
399
+ // ===========================================
400
+ "regex-dos": {
401
+ description: "Use regex with timeout or simplified pattern",
402
+ fix: (line) => '// TODO: Review regex for ReDoS - ' + line
403
+ },
404
+
405
+ // ===========================================
406
+ // PROTOTYPE POLLUTION
407
+ // ===========================================
408
+ "prototype-pollution": {
409
+ description: "Validate object keys before assignment",
410
+ fix: (line) => line.replace(/(\w+)\[(\w+)\]\s*=/, 'if (!["__proto__", "constructor", "prototype"].includes($2)) $1[$2] =')
411
+ },
412
+
413
+ // ===========================================
414
+ // DOCKERFILE
415
+ // ===========================================
416
+ "latest-tag": {
417
+ description: "Use specific version tags instead of latest",
418
+ fix: (line) => line.replace(/:latest/, ':1.0.0 # TODO: specify exact version')
419
+ },
420
+ "run-as-root": {
421
+ description: "Add USER directive to run as non-root",
422
+ fix: (line) => line + '\nUSER nonroot'
423
+ },
424
+ "add-instead-of-copy": {
425
+ description: "Use COPY instead of ADD for local files",
426
+ fix: (line) => line.replace(/^ADD\s+/, 'COPY ')
427
+ },
428
+ "curl-pipe-bash": {
429
+ description: "Download and verify scripts before execution",
430
+ fix: (line) => '# TODO: Download, verify checksum, then execute - ' + line
431
+ },
432
+ "secret-in-env": {
433
+ description: "Use Docker secrets or build args with --secret",
434
+ fix: (line) => line.replace(/ENV\s+(\w*(?:PASSWORD|SECRET|KEY|TOKEN)\w*)\s*=\s*(\S+)/, '# Use --secret instead: ENV $1=$2')
435
+ },
436
+ "secret-in-arg": {
437
+ description: "Use Docker secrets instead of ARG for secrets",
438
+ fix: (line) => line.replace(/ARG\s+(\w*(?:PASSWORD|SECRET|KEY|TOKEN)\w*)/, '# Use --secret instead: ARG $1')
439
+ },
440
+
441
+ // ===========================================
442
+ // HELMET / SECURITY HEADERS
443
+ // ===========================================
444
+ "helmet-missing": {
445
+ description: "Add helmet middleware for security headers",
446
+ fix: (line) => 'app.use(helmet()); // Add security headers\n' + line
447
+ },
448
+
449
+ // ===========================================
450
+ // SPEL INJECTION
451
+ // ===========================================
452
+ "spel-injection": {
453
+ description: "Avoid user input in SpEL expressions",
454
+ fix: (line) => '// TODO: Sanitize SpEL input - ' + line
455
+ },
456
+
457
+ // ===========================================
458
+ // ADDITIONAL DOCKERFILE FIXES
459
+ // ===========================================
460
+ "apt-get-no-version": {
461
+ description: "Pin package versions in apt-get install",
462
+ fix: (line) => line.replace(/apt-get install\s+(\w+)/, 'apt-get install $1=VERSION # TODO: specify version')
463
+ },
464
+ "pip-no-version": {
465
+ description: "Pin package versions in pip install",
466
+ fix: (line) => line.replace(/pip install\s+(\w+)/, 'pip install $1==VERSION # TODO: specify version')
467
+ },
468
+ "npm-install-unsafe": {
469
+ description: "Use npm ci for reproducible builds",
470
+ fix: (line) => line.replace(/npm install/, 'npm ci')
471
+ },
472
+ "missing-healthcheck": {
473
+ description: "Add HEALTHCHECK instruction",
474
+ fix: (line) => line + '\nHEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/ || exit 1'
475
+ },
476
+ "expose-ssh": {
477
+ description: "Avoid exposing SSH port in containers",
478
+ fix: (line) => '# SECURITY: Avoid SSH in containers - ' + line
479
+ },
480
+ "chmod-dangerous": {
481
+ description: "Use least privilege permissions",
482
+ fix: (line) => line.replace(/chmod\s+(777|666|755)/, 'chmod 644 # TODO: use least privilege')
483
+ },
484
+ "apt-no-clean": {
485
+ description: "Clean apt cache to reduce image size",
486
+ fix: (line) => line.replace(/apt-get install/, 'apt-get install -y && apt-get clean && rm -rf /var/lib/apt/lists/* #')
487
+ },
488
+ "curl-insecure": {
489
+ description: "Remove insecure flag from curl",
490
+ fix: (line) => line.replace(/curl\s+(-k|--insecure)/, 'curl')
491
+ },
492
+ "wget-no-check": {
493
+ description: "Enable certificate checking in wget",
494
+ fix: (line) => line.replace(/wget\s+--no-check-certificate/, 'wget')
495
+ },
496
+ "run-shell-form": {
497
+ description: "Use exec form for RUN commands",
498
+ fix: (line) => line.replace(/RUN\s+(.+)$/, 'RUN ["/bin/sh", "-c", "$1"]')
499
+ },
500
+ "sudo-in-dockerfile": {
501
+ description: "Avoid sudo in Dockerfile - use USER directive",
502
+ fix: (line) => line.replace(/sudo\s+/, '')
503
+ },
504
+ "workdir-absolute": {
505
+ description: "Use absolute paths in WORKDIR",
506
+ fix: (line) => line.replace(/WORKDIR\s+([^/])/, 'WORKDIR /$1')
507
+ },
508
+
509
+ // ===========================================
510
+ // ADDITIONAL TOKEN/SECRET TYPES
511
+ // ===========================================
512
+ "gcp": {
513
+ description: "Use environment variables for GCP credentials",
514
+ fix: (line, lang) => {
515
+ if (lang === 'python') return line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("GOOGLE_APPLICATION_CREDENTIALS")');
516
+ return line.replace(/=\s*["'][^"']+["']/, '= process.env.GOOGLE_APPLICATION_CREDENTIALS');
517
+ }
518
+ },
519
+ "azure": {
520
+ description: "Use environment variables for Azure credentials",
521
+ fix: (line, lang) => {
522
+ if (lang === 'python') return line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("AZURE_STORAGE_KEY")');
523
+ return line.replace(/=\s*["'][^"']+["']/, '= process.env.AZURE_STORAGE_KEY');
524
+ }
525
+ },
526
+ "npm-token": {
527
+ description: "Use environment variables for npm tokens",
528
+ fix: (line, lang) => {
529
+ if (lang === 'python') return line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("NPM_TOKEN")');
530
+ return line.replace(/=\s*["'][^"']+["']/, '= process.env.NPM_TOKEN');
531
+ }
532
+ },
533
+ "pypi": {
534
+ description: "Use environment variables for PyPI tokens",
535
+ fix: (line) => line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("PYPI_TOKEN")')
536
+ },
537
+ "discord": {
538
+ description: "Use environment variables for Discord tokens",
539
+ fix: (line, lang) => {
540
+ if (lang === 'python') return line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("DISCORD_TOKEN")');
541
+ return line.replace(/=\s*["'][^"']+["']/, '= process.env.DISCORD_TOKEN');
542
+ }
543
+ },
544
+ "shopify": {
545
+ description: "Use environment variables for Shopify tokens",
546
+ fix: (line, lang) => {
547
+ if (lang === 'python') return line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("SHOPIFY_TOKEN")');
548
+ return line.replace(/=\s*["'][^"']+["']/, '= process.env.SHOPIFY_TOKEN');
549
+ }
550
+ },
551
+ "facebook": {
552
+ description: "Use environment variables for Facebook tokens",
553
+ fix: (line, lang) => {
554
+ if (lang === 'python') return line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("FACEBOOK_TOKEN")');
555
+ return line.replace(/=\s*["'][^"']+["']/, '= process.env.FACEBOOK_TOKEN');
556
+ }
557
+ },
558
+ "twitter": {
559
+ description: "Use environment variables for Twitter tokens",
560
+ fix: (line, lang) => {
561
+ if (lang === 'python') return line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("TWITTER_BEARER_TOKEN")');
562
+ return line.replace(/=\s*["'][^"']+["']/, '= process.env.TWITTER_BEARER_TOKEN');
563
+ }
564
+ },
565
+ "gitlab": {
566
+ description: "Use environment variables for GitLab tokens",
567
+ fix: (line, lang) => {
568
+ if (lang === 'python') return line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("GITLAB_TOKEN")');
569
+ return line.replace(/=\s*["'][^"']+["']/, '= process.env.GITLAB_TOKEN');
570
+ }
571
+ },
572
+ "bitbucket": {
573
+ description: "Use environment variables for Bitbucket tokens",
574
+ fix: (line, lang) => {
575
+ if (lang === 'python') return line.replace(/=\s*["'][^"']+["']/, '= os.environ.get("BITBUCKET_TOKEN")');
576
+ return line.replace(/=\s*["'][^"']+["']/, '= process.env.BITBUCKET_TOKEN');
577
+ }
578
+ },
579
+
580
+ // ===========================================
581
+ // PROMPT INJECTION - LLM SECURITY
582
+ // ===========================================
583
+ "prompt-injection": {
584
+ description: "Sanitize user input before including in LLM prompts",
585
+ fix: (line, lang) => {
586
+ if (lang === 'python') {
587
+ return line
588
+ .replace(/f["']([^"']*)\{([^}]+)\}([^"']*)["']/, '"$1{sanitized}$3".format(sanitized=sanitize_prompt_input($2))')
589
+ .replace(/\+\s*(\w+)/, '+ sanitize_prompt_input($1)');
590
+ }
591
+ return line
592
+ .replace(/`([^`]*)\$\{([^}]+)\}([^`]*)`/, '`$1${sanitizePromptInput($2)}$3`')
593
+ .replace(/\+\s*(\w+)/, '+ sanitizePromptInput($1)');
594
+ }
595
+ },
596
+ "openai-unsafe-fstring": {
597
+ description: "Sanitize user input before including in OpenAI prompts",
598
+ fix: (line, lang) => {
599
+ if (lang === 'python') {
600
+ return line.replace(
601
+ /content\s*:\s*f["']([^"']*)["']/,
602
+ 'content: sanitize_llm_input(f"$1")'
603
+ );
604
+ }
605
+ return line.replace(/content\s*:\s*`([^`]*)`/, 'content: sanitizePromptInput(`$1`)');
606
+ }
607
+ },
608
+ "anthropic-unsafe-fstring": {
609
+ description: "Sanitize user input before including in Anthropic prompts",
610
+ fix: (line, lang) => {
611
+ if (lang === 'python') {
612
+ return line.replace(
613
+ /content\s*=\s*f["']([^"']*)["']/,
614
+ 'content=sanitize_llm_input(f"$1")'
615
+ );
616
+ }
617
+ return line.replace(/content\s*:\s*`([^`]*)`/, 'content: sanitizePromptInput(`$1`)');
618
+ }
619
+ },
620
+ "langchain-unsafe-template": {
621
+ description: "Use input validation for LangChain template variables",
622
+ fix: (line) => '# TODO: Sanitize template variables before use\n' + line
623
+ },
624
+ "langchain-chain-unsafe": {
625
+ description: "Validate user input before LangChain chain execution",
626
+ fix: (line, lang) => {
627
+ if (lang === 'python') {
628
+ return line.replace(/\.run\s*\(\s*(\w+)/, '.run(sanitize_chain_input($1)');
629
+ }
630
+ return line.replace(/\.invoke\s*\(\s*(\w+)/, '.invoke(sanitizeChainInput($1)');
631
+ }
632
+ },
633
+ "langchain-agent-unsafe": {
634
+ description: "Validate user input before LangChain agent execution",
635
+ fix: (line) => '# SECURITY: Validate and sanitize user input before agent execution\n' + line
636
+ },
637
+ "eval-llm-response": {
638
+ description: "CRITICAL: Never eval() LLM responses - use JSON parsing or ast.literal_eval for safe subset",
639
+ fix: (line, lang) => {
640
+ if (lang === 'python') {
641
+ return line.replace(/eval\s*\(\s*(\w+)/, 'ast.literal_eval($1 # SECURITY: Use safe parsing only');
642
+ }
643
+ return line.replace(/eval\s*\(\s*(\w+)/, 'JSON.parse($1 /* SECURITY: Use safe JSON parsing */');
644
+ }
645
+ },
646
+ "exec-llm-response": {
647
+ description: "CRITICAL: Never exec() LLM responses - remove or use sandboxed execution",
648
+ fix: (line) => '# SECURITY CRITICAL: Removed dangerous exec() of LLM response\n# ' + line
649
+ },
650
+ "function-constructor": {
651
+ description: "CRITICAL: Never use new Function() with LLM responses",
652
+ fix: (line) => '// SECURITY CRITICAL: Removed dangerous Function constructor with LLM response\n// ' + line
653
+ },
654
+ "pickle-llm-response": {
655
+ description: "Use JSON instead of pickle for LLM response deserialization",
656
+ fix: (line) => line.replace(/pickle\.(loads?)\s*\(/, 'json.$1(')
657
+ },
658
+ "ignore-previous-instructions": {
659
+ description: "Detected prompt injection pattern - sanitize or reject this input",
660
+ fix: (line) => '# SECURITY: Detected prompt injection attempt - INPUT SHOULD BE REJECTED\n# ' + line
661
+ },
662
+ "jailbreak-dan": {
663
+ description: "Detected DAN jailbreak attempt - reject this input",
664
+ fix: (line) => '# SECURITY: Detected jailbreak attempt - INPUT REJECTED\n# ' + line
665
+ },
666
+ "jailbreak-roleplay": {
667
+ description: "Detected role-play jailbreak attempt - sanitize or reject",
668
+ fix: (line) => '# SECURITY: Potential jailbreak via role-play - validate input\n# ' + line
669
+ },
670
+ "system-prompt-extraction": {
671
+ description: "Detected system prompt extraction attempt - reject this input",
672
+ fix: (line) => '# SECURITY: System prompt extraction attempt blocked\n# ' + line
673
+ },
674
+ "delimiter-injection": {
675
+ description: "Detected delimiter injection - escape special characters or reject",
676
+ fix: (line) => '# SECURITY: Delimiter injection blocked - escape special tokens\n# ' + line
677
+ },
678
+ "context-manipulation": {
679
+ description: "Detected context manipulation attempt - validate input",
680
+ fix: (line) => '# SECURITY: Context manipulation detected - validate user input\n# ' + line
681
+ },
682
+
683
+ // ===========================================
684
+ // ADDITIONAL SECURITY FIXES
685
+ // ===========================================
686
+ "race-condition": {
687
+ description: "Use mutex or sync primitives for shared state",
688
+ fix: (line) => '// TODO: Add mutex protection - ' + line
689
+ },
690
+ "gin-bind": {
691
+ description: "Use explicit binding in Gin handlers",
692
+ fix: (line) => line.replace(/ShouldBind\s*\(/, 'ShouldBindJSON(')
693
+ },
694
+ "permit-all": {
695
+ description: "Review permitAll() and restrict access",
696
+ fix: (line) => '// SECURITY: Review permitAll() - ' + line
697
+ }
698
+ };