@avi770/testteam 1.2.0 → 2.0.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 (300) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/README.md +53 -6
  3. package/agents/24-signup-onboarding-tester.ts +429 -0
  4. package/agents/25-crud-flow-tester.ts +302 -0
  5. package/agents/26-form-validator.ts +297 -0
  6. package/agents/27-search-filter-tester.ts +326 -0
  7. package/agents/28-navigation-routing-tester.ts +425 -0
  8. package/agents/29-responsive-interaction-tester.ts +350 -0
  9. package/agents/30-multi-user-scenario-tester.ts +319 -0
  10. package/agents/31-load-tester.ts +134 -0
  11. package/agents/32-memory-leak-detector.ts +194 -0
  12. package/agents/33-bundle-analyzer.ts +132 -0
  13. package/agents/34-xss-scanner.ts +191 -0
  14. package/agents/35-csrf-tester.ts +82 -0
  15. package/agents/36-auth-fuzzer.ts +194 -0
  16. package/agents/37-dependency-scanner.ts +176 -0
  17. package/agents/38-secrets-scanner.ts +137 -0
  18. package/agents/39-api-contract-tester.ts +199 -0
  19. package/agents/40-rate-limit-tester.ts +94 -0
  20. package/agents/41-api-pagination-tester.ts +97 -0
  21. package/agents/42-graphql-tester.ts +222 -0
  22. package/agents/43-data-consistency-checker.ts +205 -0
  23. package/agents/44-backup-recovery-tester.ts +152 -0
  24. package/agents/45-data-privacy-scanner.ts +125 -0
  25. package/agents/46-seo-auditor.ts +294 -0
  26. package/agents/47-social-preview-tester.ts +232 -0
  27. package/agents/48-lighthouse-auditor.ts +213 -0
  28. package/agents/49-i18n-tester.ts +198 -0
  29. package/agents/50-timezone-tester.ts +173 -0
  30. package/agents/51-error-recovery-tester.ts +155 -0
  31. package/agents/52-offline-mode-tester.ts +180 -0
  32. package/agents/53-graceful-degradation-tester.ts +156 -0
  33. package/agents/54-websocket-tester.ts +151 -0
  34. package/agents/55-realtime-sync-tester.ts +194 -0
  35. package/agents/56-file-upload-tester.ts +194 -0
  36. package/agents/57-export-tester.ts +174 -0
  37. package/agents/58-payment-flow-tester.ts +183 -0
  38. package/agents/59-ssl-tls-auditor.ts +141 -0
  39. package/agents/60-dns-cdn-tester.ts +117 -0
  40. package/agents/61-docker-health-checker.ts +111 -0
  41. package/agents/62-env-config-validator.ts +152 -0
  42. package/agents/63-log-quality-auditor.ts +136 -0
  43. package/agents/64-analytics-tracker-tester.ts +165 -0
  44. package/agents/65-gdpr-compliance-tester.ts +215 -0
  45. package/agents/66-soc2-control-validator.ts +210 -0
  46. package/agents/67-wcag-aaa-tester.ts +241 -0
  47. package/agents/68-dead-code-detector.ts +135 -0
  48. package/agents/69-type-safety-auditor.ts +164 -0
  49. package/agents/70-complexity-analyzer.ts +179 -0
  50. package/agents/__tests__/24-signup-onboarding-tester.test.ts +274 -0
  51. package/agents/__tests__/25-crud-flow-tester.test.ts +322 -0
  52. package/agents/__tests__/26-form-validator.test.ts +345 -0
  53. package/agents/__tests__/27-search-filter-tester.test.ts +311 -0
  54. package/agents/__tests__/28-navigation-routing-tester.test.ts +328 -0
  55. package/agents/__tests__/29-responsive-interaction-tester.test.ts +297 -0
  56. package/agents/__tests__/30-multi-user-scenario-tester.test.ts +328 -0
  57. package/agents/__tests__/31-load-tester.test.ts +189 -0
  58. package/agents/__tests__/32-memory-leak-detector.test.ts +251 -0
  59. package/agents/__tests__/33-bundle-analyzer.test.ts +237 -0
  60. package/agents/__tests__/34-xss-scanner.test.ts +258 -0
  61. package/agents/__tests__/35-csrf-tester.test.ts +200 -0
  62. package/agents/__tests__/36-auth-fuzzer.test.ts +214 -0
  63. package/agents/__tests__/37-dependency-scanner.test.ts +266 -0
  64. package/agents/__tests__/38-secrets-scanner.test.ts +224 -0
  65. package/agents/__tests__/39-api-contract-tester.test.ts +312 -0
  66. package/agents/__tests__/40-rate-limit-tester.test.ts +192 -0
  67. package/agents/__tests__/41-api-pagination-tester.test.ts +198 -0
  68. package/agents/__tests__/42-graphql-tester.test.ts +252 -0
  69. package/agents/__tests__/43-data-consistency-checker.test.ts +232 -0
  70. package/agents/__tests__/44-backup-recovery-tester.test.ts +222 -0
  71. package/agents/__tests__/45-data-privacy-scanner.test.ts +223 -0
  72. package/agents/__tests__/46-seo-auditor.test.ts +261 -0
  73. package/agents/__tests__/47-social-preview-tester.test.ts +245 -0
  74. package/agents/__tests__/48-lighthouse-auditor.test.ts +276 -0
  75. package/agents/__tests__/49-i18n-tester.test.ts +201 -0
  76. package/agents/__tests__/50-timezone-tester.test.ts +172 -0
  77. package/agents/__tests__/51-error-recovery-tester.test.ts +162 -0
  78. package/agents/__tests__/52-offline-mode-tester.test.ts +164 -0
  79. package/agents/__tests__/53-graceful-degradation-tester.test.ts +168 -0
  80. package/agents/__tests__/54-websocket-tester.test.ts +157 -0
  81. package/agents/__tests__/55-realtime-sync-tester.test.ts +181 -0
  82. package/agents/__tests__/56-file-upload-tester.test.ts +172 -0
  83. package/agents/__tests__/57-export-tester.test.ts +169 -0
  84. package/agents/__tests__/58-payment-flow-tester.test.ts +182 -0
  85. package/agents/__tests__/59-ssl-tls-auditor.test.ts +179 -0
  86. package/agents/__tests__/60-dns-cdn-tester.test.ts +176 -0
  87. package/agents/__tests__/61-docker-health-checker.test.ts +150 -0
  88. package/agents/__tests__/62-env-config-validator.test.ts +166 -0
  89. package/agents/__tests__/63-log-quality-auditor.test.ts +175 -0
  90. package/agents/__tests__/64-analytics-tracker-tester.test.ts +158 -0
  91. package/agents/__tests__/65-gdpr-compliance-tester.test.ts +174 -0
  92. package/agents/__tests__/66-soc2-control-validator.test.ts +183 -0
  93. package/agents/__tests__/67-wcag-aaa-tester.test.ts +190 -0
  94. package/agents/__tests__/68-dead-code-detector.test.ts +174 -0
  95. package/agents/__tests__/69-type-safety-auditor.test.ts +173 -0
  96. package/agents/__tests__/70-complexity-analyzer.test.ts +177 -0
  97. package/agents/__tests__/registry.test.ts +13 -13
  98. package/agents/registry.ts +146 -5
  99. package/core/__tests__/integration.test.ts +4 -4
  100. package/core/__tests__/orchestrator.test.ts +17 -16
  101. package/core/license.ts +208 -211
  102. package/core/orchestrator.ts +6 -4
  103. package/dist/agents/24-signup-onboarding-tester.d.ts +35 -0
  104. package/dist/agents/24-signup-onboarding-tester.d.ts.map +1 -0
  105. package/dist/agents/24-signup-onboarding-tester.js +357 -0
  106. package/dist/agents/24-signup-onboarding-tester.js.map +1 -0
  107. package/dist/agents/25-crud-flow-tester.d.ts +11 -0
  108. package/dist/agents/25-crud-flow-tester.d.ts.map +1 -0
  109. package/dist/agents/25-crud-flow-tester.js +253 -0
  110. package/dist/agents/25-crud-flow-tester.js.map +1 -0
  111. package/dist/agents/26-form-validator.d.ts +12 -0
  112. package/dist/agents/26-form-validator.d.ts.map +1 -0
  113. package/dist/agents/26-form-validator.js +257 -0
  114. package/dist/agents/26-form-validator.js.map +1 -0
  115. package/dist/agents/27-search-filter-tester.d.ts +20 -0
  116. package/dist/agents/27-search-filter-tester.d.ts.map +1 -0
  117. package/dist/agents/27-search-filter-tester.js +267 -0
  118. package/dist/agents/27-search-filter-tester.js.map +1 -0
  119. package/dist/agents/28-navigation-routing-tester.d.ts +32 -0
  120. package/dist/agents/28-navigation-routing-tester.d.ts.map +1 -0
  121. package/dist/agents/28-navigation-routing-tester.js +363 -0
  122. package/dist/agents/28-navigation-routing-tester.js.map +1 -0
  123. package/dist/agents/29-responsive-interaction-tester.d.ts +26 -0
  124. package/dist/agents/29-responsive-interaction-tester.d.ts.map +1 -0
  125. package/dist/agents/29-responsive-interaction-tester.js +272 -0
  126. package/dist/agents/29-responsive-interaction-tester.js.map +1 -0
  127. package/dist/agents/30-multi-user-scenario-tester.d.ts +24 -0
  128. package/dist/agents/30-multi-user-scenario-tester.d.ts.map +1 -0
  129. package/dist/agents/30-multi-user-scenario-tester.js +254 -0
  130. package/dist/agents/30-multi-user-scenario-tester.js.map +1 -0
  131. package/dist/agents/31-load-tester.d.ts +12 -0
  132. package/dist/agents/31-load-tester.d.ts.map +1 -0
  133. package/dist/agents/31-load-tester.js +110 -0
  134. package/dist/agents/31-load-tester.js.map +1 -0
  135. package/dist/agents/32-memory-leak-detector.d.ts +12 -0
  136. package/dist/agents/32-memory-leak-detector.d.ts.map +1 -0
  137. package/dist/agents/32-memory-leak-detector.js +167 -0
  138. package/dist/agents/32-memory-leak-detector.js.map +1 -0
  139. package/dist/agents/33-bundle-analyzer.d.ts +10 -0
  140. package/dist/agents/33-bundle-analyzer.d.ts.map +1 -0
  141. package/dist/agents/33-bundle-analyzer.js +111 -0
  142. package/dist/agents/33-bundle-analyzer.js.map +1 -0
  143. package/dist/agents/34-xss-scanner.d.ts +11 -0
  144. package/dist/agents/34-xss-scanner.d.ts.map +1 -0
  145. package/dist/agents/34-xss-scanner.js +164 -0
  146. package/dist/agents/34-xss-scanner.js.map +1 -0
  147. package/dist/agents/35-csrf-tester.d.ts +11 -0
  148. package/dist/agents/35-csrf-tester.d.ts.map +1 -0
  149. package/dist/agents/35-csrf-tester.js +70 -0
  150. package/dist/agents/35-csrf-tester.js.map +1 -0
  151. package/dist/agents/36-auth-fuzzer.d.ts +13 -0
  152. package/dist/agents/36-auth-fuzzer.d.ts.map +1 -0
  153. package/dist/agents/36-auth-fuzzer.js +163 -0
  154. package/dist/agents/36-auth-fuzzer.js.map +1 -0
  155. package/dist/agents/37-dependency-scanner.d.ts +11 -0
  156. package/dist/agents/37-dependency-scanner.d.ts.map +1 -0
  157. package/dist/agents/37-dependency-scanner.js +139 -0
  158. package/dist/agents/37-dependency-scanner.js.map +1 -0
  159. package/dist/agents/38-secrets-scanner.d.ts +11 -0
  160. package/dist/agents/38-secrets-scanner.d.ts.map +1 -0
  161. package/dist/agents/38-secrets-scanner.js +116 -0
  162. package/dist/agents/38-secrets-scanner.js.map +1 -0
  163. package/dist/agents/39-api-contract-tester.d.ts +12 -0
  164. package/dist/agents/39-api-contract-tester.d.ts.map +1 -0
  165. package/dist/agents/39-api-contract-tester.js +142 -0
  166. package/dist/agents/39-api-contract-tester.js.map +1 -0
  167. package/dist/agents/40-rate-limit-tester.d.ts +12 -0
  168. package/dist/agents/40-rate-limit-tester.d.ts.map +1 -0
  169. package/dist/agents/40-rate-limit-tester.js +79 -0
  170. package/dist/agents/40-rate-limit-tester.js.map +1 -0
  171. package/dist/agents/41-api-pagination-tester.d.ts +12 -0
  172. package/dist/agents/41-api-pagination-tester.d.ts.map +1 -0
  173. package/dist/agents/41-api-pagination-tester.js +79 -0
  174. package/dist/agents/41-api-pagination-tester.js.map +1 -0
  175. package/dist/agents/42-graphql-tester.d.ts +13 -0
  176. package/dist/agents/42-graphql-tester.d.ts.map +1 -0
  177. package/dist/agents/42-graphql-tester.js +187 -0
  178. package/dist/agents/42-graphql-tester.js.map +1 -0
  179. package/dist/agents/43-data-consistency-checker.d.ts +11 -0
  180. package/dist/agents/43-data-consistency-checker.d.ts.map +1 -0
  181. package/dist/agents/43-data-consistency-checker.js +176 -0
  182. package/dist/agents/43-data-consistency-checker.js.map +1 -0
  183. package/dist/agents/44-backup-recovery-tester.d.ts +11 -0
  184. package/dist/agents/44-backup-recovery-tester.d.ts.map +1 -0
  185. package/dist/agents/44-backup-recovery-tester.js +128 -0
  186. package/dist/agents/44-backup-recovery-tester.js.map +1 -0
  187. package/dist/agents/45-data-privacy-scanner.d.ts +11 -0
  188. package/dist/agents/45-data-privacy-scanner.d.ts.map +1 -0
  189. package/dist/agents/45-data-privacy-scanner.js +100 -0
  190. package/dist/agents/45-data-privacy-scanner.js.map +1 -0
  191. package/dist/agents/46-seo-auditor.d.ts +12 -0
  192. package/dist/agents/46-seo-auditor.d.ts.map +1 -0
  193. package/dist/agents/46-seo-auditor.js +275 -0
  194. package/dist/agents/46-seo-auditor.js.map +1 -0
  195. package/dist/agents/47-social-preview-tester.d.ts +11 -0
  196. package/dist/agents/47-social-preview-tester.d.ts.map +1 -0
  197. package/dist/agents/47-social-preview-tester.js +219 -0
  198. package/dist/agents/47-social-preview-tester.js.map +1 -0
  199. package/dist/agents/48-lighthouse-auditor.d.ts +11 -0
  200. package/dist/agents/48-lighthouse-auditor.d.ts.map +1 -0
  201. package/dist/agents/48-lighthouse-auditor.js +192 -0
  202. package/dist/agents/48-lighthouse-auditor.js.map +1 -0
  203. package/dist/agents/49-i18n-tester.d.ts +13 -0
  204. package/dist/agents/49-i18n-tester.d.ts.map +1 -0
  205. package/dist/agents/49-i18n-tester.js +172 -0
  206. package/dist/agents/49-i18n-tester.js.map +1 -0
  207. package/dist/agents/50-timezone-tester.d.ts +11 -0
  208. package/dist/agents/50-timezone-tester.d.ts.map +1 -0
  209. package/dist/agents/50-timezone-tester.js +152 -0
  210. package/dist/agents/50-timezone-tester.js.map +1 -0
  211. package/dist/agents/51-error-recovery-tester.d.ts +11 -0
  212. package/dist/agents/51-error-recovery-tester.d.ts.map +1 -0
  213. package/dist/agents/51-error-recovery-tester.js +134 -0
  214. package/dist/agents/51-error-recovery-tester.js.map +1 -0
  215. package/dist/agents/52-offline-mode-tester.d.ts +12 -0
  216. package/dist/agents/52-offline-mode-tester.d.ts.map +1 -0
  217. package/dist/agents/52-offline-mode-tester.js +161 -0
  218. package/dist/agents/52-offline-mode-tester.js.map +1 -0
  219. package/dist/agents/53-graceful-degradation-tester.d.ts +12 -0
  220. package/dist/agents/53-graceful-degradation-tester.d.ts.map +1 -0
  221. package/dist/agents/53-graceful-degradation-tester.js +130 -0
  222. package/dist/agents/53-graceful-degradation-tester.js.map +1 -0
  223. package/dist/agents/54-websocket-tester.d.ts +10 -0
  224. package/dist/agents/54-websocket-tester.d.ts.map +1 -0
  225. package/dist/agents/54-websocket-tester.js +132 -0
  226. package/dist/agents/54-websocket-tester.js.map +1 -0
  227. package/dist/agents/55-realtime-sync-tester.d.ts +11 -0
  228. package/dist/agents/55-realtime-sync-tester.d.ts.map +1 -0
  229. package/dist/agents/55-realtime-sync-tester.js +175 -0
  230. package/dist/agents/55-realtime-sync-tester.js.map +1 -0
  231. package/dist/agents/56-file-upload-tester.d.ts +12 -0
  232. package/dist/agents/56-file-upload-tester.d.ts.map +1 -0
  233. package/dist/agents/56-file-upload-tester.js +166 -0
  234. package/dist/agents/56-file-upload-tester.js.map +1 -0
  235. package/dist/agents/57-export-tester.d.ts +11 -0
  236. package/dist/agents/57-export-tester.d.ts.map +1 -0
  237. package/dist/agents/57-export-tester.js +155 -0
  238. package/dist/agents/57-export-tester.js.map +1 -0
  239. package/dist/agents/58-payment-flow-tester.d.ts +11 -0
  240. package/dist/agents/58-payment-flow-tester.d.ts.map +1 -0
  241. package/dist/agents/58-payment-flow-tester.js +159 -0
  242. package/dist/agents/58-payment-flow-tester.js.map +1 -0
  243. package/dist/agents/59-ssl-tls-auditor.d.ts +10 -0
  244. package/dist/agents/59-ssl-tls-auditor.d.ts.map +1 -0
  245. package/dist/agents/59-ssl-tls-auditor.js +132 -0
  246. package/dist/agents/59-ssl-tls-auditor.js.map +1 -0
  247. package/dist/agents/60-dns-cdn-tester.d.ts +10 -0
  248. package/dist/agents/60-dns-cdn-tester.d.ts.map +1 -0
  249. package/dist/agents/60-dns-cdn-tester.js +105 -0
  250. package/dist/agents/60-dns-cdn-tester.js.map +1 -0
  251. package/dist/agents/61-docker-health-checker.d.ts +10 -0
  252. package/dist/agents/61-docker-health-checker.d.ts.map +1 -0
  253. package/dist/agents/61-docker-health-checker.js +95 -0
  254. package/dist/agents/61-docker-health-checker.js.map +1 -0
  255. package/dist/agents/62-env-config-validator.d.ts +10 -0
  256. package/dist/agents/62-env-config-validator.d.ts.map +1 -0
  257. package/dist/agents/62-env-config-validator.js +132 -0
  258. package/dist/agents/62-env-config-validator.js.map +1 -0
  259. package/dist/agents/63-log-quality-auditor.d.ts +9 -0
  260. package/dist/agents/63-log-quality-auditor.d.ts.map +1 -0
  261. package/dist/agents/63-log-quality-auditor.js +121 -0
  262. package/dist/agents/63-log-quality-auditor.js.map +1 -0
  263. package/dist/agents/64-analytics-tracker-tester.d.ts +10 -0
  264. package/dist/agents/64-analytics-tracker-tester.d.ts.map +1 -0
  265. package/dist/agents/64-analytics-tracker-tester.js +146 -0
  266. package/dist/agents/64-analytics-tracker-tester.js.map +1 -0
  267. package/dist/agents/65-gdpr-compliance-tester.d.ts +13 -0
  268. package/dist/agents/65-gdpr-compliance-tester.d.ts.map +1 -0
  269. package/dist/agents/65-gdpr-compliance-tester.js +186 -0
  270. package/dist/agents/65-gdpr-compliance-tester.js.map +1 -0
  271. package/dist/agents/66-soc2-control-validator.d.ts +14 -0
  272. package/dist/agents/66-soc2-control-validator.d.ts.map +1 -0
  273. package/dist/agents/66-soc2-control-validator.js +178 -0
  274. package/dist/agents/66-soc2-control-validator.js.map +1 -0
  275. package/dist/agents/67-wcag-aaa-tester.d.ts +13 -0
  276. package/dist/agents/67-wcag-aaa-tester.d.ts.map +1 -0
  277. package/dist/agents/67-wcag-aaa-tester.js +207 -0
  278. package/dist/agents/67-wcag-aaa-tester.js.map +1 -0
  279. package/dist/agents/68-dead-code-detector.d.ts +9 -0
  280. package/dist/agents/68-dead-code-detector.d.ts.map +1 -0
  281. package/dist/agents/68-dead-code-detector.js +116 -0
  282. package/dist/agents/68-dead-code-detector.js.map +1 -0
  283. package/dist/agents/69-type-safety-auditor.d.ts +9 -0
  284. package/dist/agents/69-type-safety-auditor.d.ts.map +1 -0
  285. package/dist/agents/69-type-safety-auditor.js +148 -0
  286. package/dist/agents/69-type-safety-auditor.js.map +1 -0
  287. package/dist/agents/70-complexity-analyzer.d.ts +10 -0
  288. package/dist/agents/70-complexity-analyzer.d.ts.map +1 -0
  289. package/dist/agents/70-complexity-analyzer.js +154 -0
  290. package/dist/agents/70-complexity-analyzer.js.map +1 -0
  291. package/dist/agents/registry.d.ts +3 -3
  292. package/dist/agents/registry.d.ts.map +1 -1
  293. package/dist/agents/registry.js +146 -5
  294. package/dist/agents/registry.js.map +1 -1
  295. package/dist/core/license.js +2 -5
  296. package/dist/core/license.js.map +1 -1
  297. package/dist/core/orchestrator.d.ts.map +1 -1
  298. package/dist/core/orchestrator.js +6 -4
  299. package/dist/core/orchestrator.js.map +1 -1
  300. package/package.json +2 -2
@@ -0,0 +1,82 @@
1
+ import type { Finding } from '../core/types';
2
+ import { BaseAgent } from './base-agent';
3
+ import { resolveEnvironment } from '../helpers/env-resolver';
4
+
5
+ /** Common POST endpoints to test for CSRF protection. */
6
+ const DEFAULT_POST_ENDPOINTS = [
7
+ '/api/auth/login',
8
+ '/api/tasks',
9
+ '/api/clients',
10
+ ] as const;
11
+
12
+ const REQUEST_TIMEOUT_MS = 10_000;
13
+
14
+ export class CsrfTesterAgent extends BaseAgent {
15
+ readonly agentId = 35;
16
+ readonly agentName = 'CSRF Tester';
17
+ private baseUrl = '';
18
+
19
+ protected async preFlight(): Promise<void> {
20
+ const { env } = await resolveEnvironment(this.config, this.phase);
21
+ this.baseUrl = env.baseUrl;
22
+ }
23
+
24
+ protected async execute(): Promise<Finding[]> {
25
+ const findings: Finding[] = [];
26
+ const endpoints = this.discoverEndpoints();
27
+
28
+ for (const endpoint of endpoints) {
29
+ const url = `${this.baseUrl}${endpoint}`;
30
+
31
+ try {
32
+ const response = await Promise.race([
33
+ fetch(url, {
34
+ method: 'POST',
35
+ headers: { 'Content-Type': 'application/json' },
36
+ body: JSON.stringify({ test: 'csrf-probe' }),
37
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
38
+ }),
39
+ new Promise<never>((_, reject) =>
40
+ setTimeout(() => reject(new Error('CSRF test timeout')), REQUEST_TIMEOUT_MS),
41
+ ),
42
+ ]) as Response;
43
+
44
+ if (response.status === 200 || response.status === 201) {
45
+ findings.push({
46
+ id: `${this.agentId}-no-csrf-${endpoint.replace(/\//g, '_')}`,
47
+ type: 'code-bug-security',
48
+ severity: 'high',
49
+ agentId: this.agentId,
50
+ module: 'csrf-tester',
51
+ description: `Endpoint ${endpoint} accepts POST requests without CSRF protection (status ${response.status})`,
52
+ });
53
+ }
54
+
55
+ this.addEvidence({
56
+ type: 'log',
57
+ path: `csrf-test-${endpoint.replace(/\//g, '_')}`,
58
+ description: `POST ${endpoint} without auth/CSRF headers: status=${response.status}`,
59
+ });
60
+ } catch (error) {
61
+ findings.push({
62
+ id: `${this.agentId}-request-failed-${endpoint.replace(/\//g, '_')}`,
63
+ type: 'infra-issue',
64
+ severity: 'low',
65
+ agentId: this.agentId,
66
+ module: 'csrf-tester',
67
+ description: `Failed to test endpoint ${endpoint}: ${error instanceof Error ? error.message : String(error)}`,
68
+ });
69
+ }
70
+ }
71
+
72
+ return findings;
73
+ }
74
+
75
+ private discoverEndpoints(): string[] {
76
+ if (this.config.modules && this.config.modules.length > 0) {
77
+ const moduleEndpoints = this.config.modules.map(m => `/api${m.route}`);
78
+ return [...new Set([...DEFAULT_POST_ENDPOINTS, ...moduleEndpoints])];
79
+ }
80
+ return [...DEFAULT_POST_ENDPOINTS];
81
+ }
82
+ }
@@ -0,0 +1,194 @@
1
+ import type { Finding } from '../core/types';
2
+ import { BaseAgent } from './base-agent';
3
+ import { resolveEnvironment } from '../helpers/env-resolver';
4
+
5
+ const REQUEST_TIMEOUT_MS = 10_000;
6
+ const LOCKOUT_ATTEMPTS = 10;
7
+
8
+ export class AuthFuzzerAgent extends BaseAgent {
9
+ readonly agentId = 36;
10
+ readonly agentName = 'Auth Fuzzer';
11
+ private baseUrl = '';
12
+
13
+ protected async preFlight(): Promise<void> {
14
+ const { env } = await resolveEnvironment(this.config, this.phase);
15
+ this.baseUrl = env.baseUrl;
16
+ }
17
+
18
+ protected async execute(): Promise<Finding[]> {
19
+ const findings: Finding[] = [];
20
+
21
+ // Test 1: SQL injection in login
22
+ const sqlInjectionFindings = await this.testSqlInjection();
23
+ findings.push(...sqlInjectionFindings);
24
+
25
+ // Test 2: Account lockout
26
+ const lockoutFindings = await this.testAccountLockout();
27
+ findings.push(...lockoutFindings);
28
+
29
+ // Test 3: JWT alg:none bypass
30
+ const jwtFindings = await this.testJwtAlgNone();
31
+ findings.push(...jwtFindings);
32
+
33
+ return findings;
34
+ }
35
+
36
+ private async testSqlInjection(): Promise<Finding[]> {
37
+ const findings: Finding[] = [];
38
+ const loginUrl = `${this.baseUrl}/api/auth/login`;
39
+
40
+ try {
41
+ const response = await Promise.race([
42
+ fetch(loginUrl, {
43
+ method: 'POST',
44
+ headers: { 'Content-Type': 'application/json' },
45
+ body: JSON.stringify({
46
+ email: "' OR 1=1 --",
47
+ password: 'anything',
48
+ }),
49
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
50
+ }),
51
+ new Promise<never>((_, reject) =>
52
+ setTimeout(() => reject(new Error('Timeout')), REQUEST_TIMEOUT_MS),
53
+ ),
54
+ ]) as Response;
55
+
56
+ if (response.status === 200 || response.status === 201) {
57
+ findings.push({
58
+ id: `${this.agentId}-sql-injection-login`,
59
+ type: 'code-bug-security',
60
+ severity: 'critical',
61
+ agentId: this.agentId,
62
+ module: 'auth-fuzzer',
63
+ description: `SQL injection in login succeeded — endpoint returned ${response.status} for malicious email input`,
64
+ });
65
+ }
66
+
67
+ this.addEvidence({
68
+ type: 'log',
69
+ path: 'sql-injection-test',
70
+ description: `SQL injection login test: status=${response.status}`,
71
+ });
72
+ } catch (error) {
73
+ findings.push({
74
+ id: `${this.agentId}-sql-injection-error`,
75
+ type: 'infra-issue',
76
+ severity: 'low',
77
+ agentId: this.agentId,
78
+ module: 'auth-fuzzer',
79
+ description: `SQL injection test failed to execute: ${error instanceof Error ? error.message : String(error)}`,
80
+ });
81
+ }
82
+
83
+ return findings;
84
+ }
85
+
86
+ private async testAccountLockout(): Promise<Finding[]> {
87
+ const findings: Finding[] = [];
88
+ const loginUrl = `${this.baseUrl}/api/auth/login`;
89
+ let got429 = false;
90
+
91
+ for (let i = 0; i < LOCKOUT_ATTEMPTS; i++) {
92
+ try {
93
+ const response = await Promise.race([
94
+ fetch(loginUrl, {
95
+ method: 'POST',
96
+ headers: { 'Content-Type': 'application/json' },
97
+ body: JSON.stringify({
98
+ email: 'lockout-test@example.com',
99
+ password: `wrong-password-${i}`,
100
+ }),
101
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
102
+ }),
103
+ new Promise<never>((_, reject) =>
104
+ setTimeout(() => reject(new Error('Timeout')), REQUEST_TIMEOUT_MS),
105
+ ),
106
+ ]) as Response;
107
+
108
+ if (response.status === 429) {
109
+ got429 = true;
110
+ break;
111
+ }
112
+ } catch {
113
+ // Request failed — continue testing
114
+ }
115
+ }
116
+
117
+ if (!got429) {
118
+ findings.push({
119
+ id: `${this.agentId}-no-lockout`,
120
+ type: 'code-bug-security',
121
+ severity: 'medium',
122
+ agentId: this.agentId,
123
+ module: 'auth-fuzzer',
124
+ description: `No account lockout after ${LOCKOUT_ATTEMPTS} failed login attempts — no 429 response received`,
125
+ });
126
+ }
127
+
128
+ this.addEvidence({
129
+ type: 'log',
130
+ path: 'lockout-test',
131
+ description: `Account lockout test: ${got429 ? 'lockout triggered' : 'no lockout detected'} after ${LOCKOUT_ATTEMPTS} attempts`,
132
+ });
133
+
134
+ return findings;
135
+ }
136
+
137
+ private async testJwtAlgNone(): Promise<Finding[]> {
138
+ const findings: Finding[] = [];
139
+
140
+ // Create a JWT with alg: "none"
141
+ const header = Buffer.from(JSON.stringify({ alg: 'none', typ: 'JWT' })).toString('base64url');
142
+ const payload = Buffer.from(
143
+ JSON.stringify({ sub: '1', email: 'admin@test.com', role: 'admin', iat: Math.floor(Date.now() / 1000) }),
144
+ ).toString('base64url');
145
+ const fakeJwt = `${header}.${payload}.`;
146
+
147
+ // Try accessing a protected endpoint
148
+ const protectedUrl = `${this.baseUrl}/api/tasks`;
149
+
150
+ try {
151
+ const response = await Promise.race([
152
+ fetch(protectedUrl, {
153
+ method: 'GET',
154
+ headers: {
155
+ 'Authorization': `Bearer ${fakeJwt}`,
156
+ 'Content-Type': 'application/json',
157
+ },
158
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
159
+ }),
160
+ new Promise<never>((_, reject) =>
161
+ setTimeout(() => reject(new Error('Timeout')), REQUEST_TIMEOUT_MS),
162
+ ),
163
+ ]) as Response;
164
+
165
+ if (response.status === 200) {
166
+ findings.push({
167
+ id: `${this.agentId}-jwt-alg-none`,
168
+ type: 'code-bug-security',
169
+ severity: 'critical',
170
+ agentId: this.agentId,
171
+ module: 'auth-fuzzer',
172
+ description: `Protected endpoint accepts JWT with alg:"none" — authentication bypass vulnerability`,
173
+ });
174
+ }
175
+
176
+ this.addEvidence({
177
+ type: 'log',
178
+ path: 'jwt-alg-none-test',
179
+ description: `JWT alg:none test: status=${response.status}`,
180
+ });
181
+ } catch (error) {
182
+ findings.push({
183
+ id: `${this.agentId}-jwt-test-error`,
184
+ type: 'infra-issue',
185
+ severity: 'low',
186
+ agentId: this.agentId,
187
+ module: 'auth-fuzzer',
188
+ description: `JWT alg:none test failed to execute: ${error instanceof Error ? error.message : String(error)}`,
189
+ });
190
+ }
191
+
192
+ return findings;
193
+ }
194
+ }
@@ -0,0 +1,176 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import type { Finding } from '../core/types';
4
+ import { BaseAgent } from './base-agent';
5
+
6
+ const execFileAsync = promisify(execFile);
7
+
8
+ interface AuditVulnerability {
9
+ severity: string;
10
+ name: string;
11
+ title?: string;
12
+ url?: string;
13
+ range?: string;
14
+ }
15
+
16
+ interface AuditReport {
17
+ vulnerabilities?: Record<string, AuditVulnerability>;
18
+ }
19
+
20
+ interface OutdatedEntry {
21
+ current: string;
22
+ wanted: string;
23
+ latest: string;
24
+ type?: string;
25
+ }
26
+
27
+ type SeverityMap = Record<string, 'critical' | 'high' | 'medium' | 'low'>;
28
+
29
+ const SEVERITY_MAP: SeverityMap = {
30
+ critical: 'critical',
31
+ high: 'high',
32
+ moderate: 'medium',
33
+ low: 'low',
34
+ info: 'low',
35
+ };
36
+
37
+ export class DependencyScannerAgent extends BaseAgent {
38
+ readonly agentId = 37;
39
+ readonly agentName = 'Dependency Scanner';
40
+
41
+ protected async preFlight(): Promise<void> {
42
+ // No special pre-conditions
43
+ }
44
+
45
+ protected async execute(): Promise<Finding[]> {
46
+ const findings: Finding[] = [];
47
+ const projectRoot = this.config.projectRoot ?? process.cwd();
48
+
49
+ // Run npm audit
50
+ const auditFindings = await this.runAudit(projectRoot);
51
+ findings.push(...auditFindings);
52
+
53
+ // Run npm outdated
54
+ const outdatedFindings = await this.runOutdated(projectRoot);
55
+ findings.push(...outdatedFindings);
56
+
57
+ return findings;
58
+ }
59
+
60
+ private async runAudit(projectRoot: string): Promise<Finding[]> {
61
+ const findings: Finding[] = [];
62
+
63
+ try {
64
+ let stdout: string;
65
+ try {
66
+ const result = await execFileAsync('npm', ['audit', '--json'], {
67
+ cwd: projectRoot,
68
+ timeout: 60_000,
69
+ });
70
+ stdout = result.stdout;
71
+ } catch (execError) {
72
+ // npm audit exits non-zero when vulnerabilities are found
73
+ const err = execError as { stdout?: string; stderr?: string };
74
+ if (err.stdout) {
75
+ stdout = err.stdout;
76
+ } else {
77
+ throw execError;
78
+ }
79
+ }
80
+
81
+ const report: AuditReport = JSON.parse(stdout);
82
+ const vulnerabilities = report.vulnerabilities ?? {};
83
+
84
+ for (const [name, vuln] of Object.entries(vulnerabilities)) {
85
+ const severity = SEVERITY_MAP[vuln.severity] ?? 'medium';
86
+ findings.push({
87
+ id: `${this.agentId}-vuln-${name}`,
88
+ type: 'code-bug-security',
89
+ severity,
90
+ agentId: this.agentId,
91
+ module: 'dependency-scanner',
92
+ description: `Vulnerability in ${name}: ${vuln.title ?? vuln.severity} (${vuln.url ?? 'no URL'})`,
93
+ });
94
+ }
95
+
96
+ this.addEvidence({
97
+ type: 'report',
98
+ path: 'npm-audit',
99
+ description: `npm audit found ${Object.keys(vulnerabilities).length} vulnerable packages`,
100
+ });
101
+ } catch (error) {
102
+ findings.push({
103
+ id: `${this.agentId}-audit-error`,
104
+ type: 'infra-issue',
105
+ severity: 'medium',
106
+ agentId: this.agentId,
107
+ module: 'dependency-scanner',
108
+ description: `npm audit failed: ${error instanceof Error ? error.message : String(error)}`,
109
+ });
110
+ }
111
+
112
+ return findings;
113
+ }
114
+
115
+ private async runOutdated(projectRoot: string): Promise<Finding[]> {
116
+ const findings: Finding[] = [];
117
+
118
+ try {
119
+ let stdout: string;
120
+ try {
121
+ const result = await execFileAsync('npm', ['outdated', '--json'], {
122
+ cwd: projectRoot,
123
+ timeout: 60_000,
124
+ });
125
+ stdout = result.stdout;
126
+ } catch (execError) {
127
+ // npm outdated exits non-zero when there are outdated packages
128
+ const err = execError as { stdout?: string; stderr?: string };
129
+ if (err.stdout) {
130
+ stdout = err.stdout;
131
+ } else {
132
+ throw execError;
133
+ }
134
+ }
135
+
136
+ if (!stdout || stdout.trim() === '') {
137
+ return findings;
138
+ }
139
+
140
+ const outdated: Record<string, OutdatedEntry> = JSON.parse(stdout);
141
+
142
+ for (const [name, info] of Object.entries(outdated)) {
143
+ const currentMajor = parseInt(info.current.split('.')[0], 10);
144
+ const latestMajor = parseInt(info.latest.split('.')[0], 10);
145
+
146
+ if (latestMajor - currentMajor >= 1) {
147
+ findings.push({
148
+ id: `${this.agentId}-outdated-${name}`,
149
+ type: 'test-bug',
150
+ severity: 'low',
151
+ agentId: this.agentId,
152
+ module: 'dependency-scanner',
153
+ description: `Package ${name} is ${latestMajor - currentMajor} major version(s) behind: current=${info.current}, latest=${info.latest}`,
154
+ });
155
+ }
156
+ }
157
+
158
+ this.addEvidence({
159
+ type: 'report',
160
+ path: 'npm-outdated',
161
+ description: `npm outdated found ${Object.keys(outdated).length} outdated packages`,
162
+ });
163
+ } catch (error) {
164
+ findings.push({
165
+ id: `${this.agentId}-outdated-error`,
166
+ type: 'infra-issue',
167
+ severity: 'low',
168
+ agentId: this.agentId,
169
+ module: 'dependency-scanner',
170
+ description: `npm outdated failed: ${error instanceof Error ? error.message : String(error)}`,
171
+ });
172
+ }
173
+
174
+ return findings;
175
+ }
176
+ }
@@ -0,0 +1,137 @@
1
+ import { readdir, readFile, stat } from 'node:fs/promises';
2
+ import { join, extname } from 'node:path';
3
+ import type { Finding } from '../core/types';
4
+ import { BaseAgent } from './base-agent';
5
+
6
+ /** File extensions to scan for secrets. */
7
+ const SCANNABLE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.json', '.env']);
8
+
9
+ /** Maximum file size to scan (1MB). */
10
+ const MAX_FILE_SIZE = 1024 * 1024;
11
+
12
+ /** Directories to skip. */
13
+ const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'out', 'coverage', '.next']);
14
+
15
+ interface SecretPattern {
16
+ name: string;
17
+ regex: RegExp;
18
+ }
19
+
20
+ const SECRET_PATTERNS: SecretPattern[] = [
21
+ { name: 'AWS Access Key', regex: /AKIA[0-9A-Z]{16}/g },
22
+ { name: 'Stripe Live Key', regex: /sk_live_[a-zA-Z0-9]+/g },
23
+ { name: 'Hardcoded Password', regex: /password\s*[:=]\s*['"][^'"]+/gi },
24
+ { name: 'Private Key', regex: /-----BEGIN.*PRIVATE KEY-----/g },
25
+ ];
26
+
27
+ export class SecretsScannerAgent extends BaseAgent {
28
+ readonly agentId = 38;
29
+ readonly agentName = 'Secrets Scanner';
30
+
31
+ protected async preFlight(): Promise<void> {
32
+ // No special pre-conditions
33
+ }
34
+
35
+ protected async execute(): Promise<Finding[]> {
36
+ const findings: Finding[] = [];
37
+ const projectRoot = this.config.projectRoot ?? process.cwd();
38
+
39
+ let scannedFiles = 0;
40
+ let totalMatches = 0;
41
+
42
+ try {
43
+ const files = await this.collectFiles(projectRoot);
44
+ scannedFiles = files.length;
45
+
46
+ for (const filePath of files) {
47
+ const fileFindings = await this.scanFile(filePath);
48
+ totalMatches += fileFindings.length;
49
+ findings.push(...fileFindings);
50
+ }
51
+ } catch (error) {
52
+ findings.push({
53
+ id: `${this.agentId}-scan-error`,
54
+ type: 'infra-issue',
55
+ severity: 'medium',
56
+ agentId: this.agentId,
57
+ module: 'secrets-scanner',
58
+ description: `Failed to scan project files: ${error instanceof Error ? error.message : String(error)}`,
59
+ });
60
+ }
61
+
62
+ this.addEvidence({
63
+ type: 'report',
64
+ path: 'secrets-scan',
65
+ description: `Scanned ${scannedFiles} files, found ${totalMatches} potential secrets`,
66
+ });
67
+
68
+ return findings;
69
+ }
70
+
71
+ private async collectFiles(dir: string, depth = 0): Promise<string[]> {
72
+ if (depth > 5) return [];
73
+
74
+ const files: string[] = [];
75
+
76
+ try {
77
+ const entries = await readdir(dir, { withFileTypes: true });
78
+
79
+ for (const entry of entries) {
80
+ if (SKIP_DIRS.has(entry.name)) continue;
81
+
82
+ const fullPath = join(dir, entry.name);
83
+
84
+ if (entry.isDirectory()) {
85
+ const subFiles = await this.collectFiles(fullPath, depth + 1);
86
+ files.push(...subFiles);
87
+ } else if (entry.isFile() && SCANNABLE_EXTENSIONS.has(extname(entry.name))) {
88
+ try {
89
+ const fileStat = await stat(fullPath);
90
+ if (fileStat.size <= MAX_FILE_SIZE) {
91
+ files.push(fullPath);
92
+ }
93
+ } catch {
94
+ // Skip inaccessible files
95
+ }
96
+ }
97
+ }
98
+ } catch {
99
+ // Skip inaccessible directories
100
+ }
101
+
102
+ return files;
103
+ }
104
+
105
+ private async scanFile(filePath: string): Promise<Finding[]> {
106
+ const findings: Finding[] = [];
107
+
108
+ try {
109
+ const content = await readFile(filePath, 'utf-8');
110
+ const lines = content.split('\n');
111
+
112
+ for (const pattern of SECRET_PATTERNS) {
113
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
114
+ const line = lines[lineIdx];
115
+ // Reset regex lastIndex for global patterns
116
+ pattern.regex.lastIndex = 0;
117
+ if (pattern.regex.test(line)) {
118
+ findings.push({
119
+ id: `${this.agentId}-secret-${pattern.name.replace(/\s/g, '-').toLowerCase()}-${filePath.replace(/[\\/]/g, '_')}-L${lineIdx + 1}`,
120
+ type: 'code-bug-security',
121
+ severity: 'high',
122
+ agentId: this.agentId,
123
+ module: 'secrets-scanner',
124
+ file: filePath,
125
+ line: lineIdx + 1,
126
+ description: `Potential ${pattern.name} found in ${filePath} at line ${lineIdx + 1}`,
127
+ });
128
+ }
129
+ }
130
+ }
131
+ } catch {
132
+ // Skip unreadable files
133
+ }
134
+
135
+ return findings;
136
+ }
137
+ }