vaspera 2.9.2 → 2.10.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 (159) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +58 -1
  3. package/dist/__tests__/autofix/branch-manager.test.d.ts +2 -0
  4. package/dist/__tests__/autofix/branch-manager.test.d.ts.map +1 -0
  5. package/dist/__tests__/autofix/branch-manager.test.js +60 -0
  6. package/dist/__tests__/autofix/branch-manager.test.js.map +1 -0
  7. package/dist/__tests__/autofix/commit-generator.test.d.ts +2 -0
  8. package/dist/__tests__/autofix/commit-generator.test.d.ts.map +1 -0
  9. package/dist/__tests__/autofix/commit-generator.test.js +147 -0
  10. package/dist/__tests__/autofix/commit-generator.test.js.map +1 -0
  11. package/dist/__tests__/autofix/constitution.test.d.ts +9 -0
  12. package/dist/__tests__/autofix/constitution.test.d.ts.map +1 -0
  13. package/dist/__tests__/autofix/constitution.test.js +421 -0
  14. package/dist/__tests__/autofix/constitution.test.js.map +1 -0
  15. package/dist/__tests__/autofix/pr-generator.test.d.ts +2 -0
  16. package/dist/__tests__/autofix/pr-generator.test.d.ts.map +1 -0
  17. package/dist/__tests__/autofix/pr-generator.test.js +152 -0
  18. package/dist/__tests__/autofix/pr-generator.test.js.map +1 -0
  19. package/dist/__tests__/property-test-helpers.d.ts +87 -0
  20. package/dist/__tests__/property-test-helpers.d.ts.map +1 -0
  21. package/dist/__tests__/property-test-helpers.js +136 -0
  22. package/dist/__tests__/property-test-helpers.js.map +1 -0
  23. package/dist/__tests__/scanners/dast/index.test.d.ts +2 -0
  24. package/dist/__tests__/scanners/dast/index.test.d.ts.map +1 -0
  25. package/dist/__tests__/scanners/dast/index.test.js +183 -0
  26. package/dist/__tests__/scanners/dast/index.test.js.map +1 -0
  27. package/dist/__tests__/scanners/dast/nuclei.test.d.ts +2 -0
  28. package/dist/__tests__/scanners/dast/nuclei.test.d.ts.map +1 -0
  29. package/dist/__tests__/scanners/dast/nuclei.test.js +166 -0
  30. package/dist/__tests__/scanners/dast/nuclei.test.js.map +1 -0
  31. package/dist/__tests__/scanners/dast/zap.test.d.ts +2 -0
  32. package/dist/__tests__/scanners/dast/zap.test.d.ts.map +1 -0
  33. package/dist/__tests__/scanners/dast/zap.test.js +158 -0
  34. package/dist/__tests__/scanners/dast/zap.test.js.map +1 -0
  35. package/dist/__tests__/scanners/fp-feedback.test.d.ts +2 -0
  36. package/dist/__tests__/scanners/fp-feedback.test.d.ts.map +1 -0
  37. package/dist/__tests__/scanners/fp-feedback.test.js +202 -0
  38. package/dist/__tests__/scanners/fp-feedback.test.js.map +1 -0
  39. package/dist/__tests__/scanners/fp-filter.property.test.d.ts +9 -0
  40. package/dist/__tests__/scanners/fp-filter.property.test.d.ts.map +1 -0
  41. package/dist/__tests__/scanners/fp-filter.property.test.js +253 -0
  42. package/dist/__tests__/scanners/fp-filter.property.test.js.map +1 -0
  43. package/dist/__tests__/scanners/fp-filter.test.d.ts +2 -0
  44. package/dist/__tests__/scanners/fp-filter.test.d.ts.map +1 -0
  45. package/dist/__tests__/scanners/fp-filter.test.js +234 -0
  46. package/dist/__tests__/scanners/fp-filter.test.js.map +1 -0
  47. package/dist/__tests__/scanners/fp-tracker.test.d.ts +2 -0
  48. package/dist/__tests__/scanners/fp-tracker.test.d.ts.map +1 -0
  49. package/dist/__tests__/scanners/fp-tracker.test.js +262 -0
  50. package/dist/__tests__/scanners/fp-tracker.test.js.map +1 -0
  51. package/dist/__tests__/scanners/logic/endpoint-analyzer.property.test.d.ts +10 -0
  52. package/dist/__tests__/scanners/logic/endpoint-analyzer.property.test.d.ts.map +1 -0
  53. package/dist/__tests__/scanners/logic/endpoint-analyzer.property.test.js +238 -0
  54. package/dist/__tests__/scanners/logic/endpoint-analyzer.property.test.js.map +1 -0
  55. package/dist/__tests__/scanners/logic/endpoint-analyzer.test.d.ts +2 -0
  56. package/dist/__tests__/scanners/logic/endpoint-analyzer.test.d.ts.map +1 -0
  57. package/dist/__tests__/scanners/logic/endpoint-analyzer.test.js +55 -0
  58. package/dist/__tests__/scanners/logic/endpoint-analyzer.test.js.map +1 -0
  59. package/dist/__tests__/scanners/logic/index.test.d.ts +2 -0
  60. package/dist/__tests__/scanners/logic/index.test.d.ts.map +1 -0
  61. package/dist/__tests__/scanners/logic/index.test.js +165 -0
  62. package/dist/__tests__/scanners/logic/index.test.js.map +1 -0
  63. package/dist/__tests__/scanners/logic/types.test.d.ts +2 -0
  64. package/dist/__tests__/scanners/logic/types.test.d.ts.map +1 -0
  65. package/dist/__tests__/scanners/logic/types.test.js +85 -0
  66. package/dist/__tests__/scanners/logic/types.test.js.map +1 -0
  67. package/dist/action/pr-comment.test.js +4 -0
  68. package/dist/action/pr-comment.test.js.map +1 -1
  69. package/dist/action/sarif-upload.test.js +4 -0
  70. package/dist/action/sarif-upload.test.js.map +1 -1
  71. package/dist/autofix/branch-manager.d.ts +115 -0
  72. package/dist/autofix/branch-manager.d.ts.map +1 -0
  73. package/dist/autofix/branch-manager.js +308 -0
  74. package/dist/autofix/branch-manager.js.map +1 -0
  75. package/dist/autofix/commit-generator.d.ts +55 -0
  76. package/dist/autofix/commit-generator.d.ts.map +1 -0
  77. package/dist/autofix/commit-generator.js +277 -0
  78. package/dist/autofix/commit-generator.js.map +1 -0
  79. package/dist/autofix/constitution.d.ts +77 -0
  80. package/dist/autofix/constitution.d.ts.map +1 -0
  81. package/dist/autofix/constitution.js +261 -0
  82. package/dist/autofix/constitution.js.map +1 -0
  83. package/dist/autofix/constitution.schema.d.ts +441 -0
  84. package/dist/autofix/constitution.schema.d.ts.map +1 -0
  85. package/dist/autofix/constitution.schema.js +144 -0
  86. package/dist/autofix/constitution.schema.js.map +1 -0
  87. package/dist/autofix/index.d.ts +13 -0
  88. package/dist/autofix/index.d.ts.map +1 -0
  89. package/dist/autofix/index.js +15 -0
  90. package/dist/autofix/index.js.map +1 -0
  91. package/dist/autofix/pr-generator.d.ts +57 -0
  92. package/dist/autofix/pr-generator.d.ts.map +1 -0
  93. package/dist/autofix/pr-generator.js +597 -0
  94. package/dist/autofix/pr-generator.js.map +1 -0
  95. package/dist/autofix/types.d.ts +151 -0
  96. package/dist/autofix/types.d.ts.map +1 -0
  97. package/dist/autofix/types.js +22 -0
  98. package/dist/autofix/types.js.map +1 -0
  99. package/dist/eval/fixtures.d.ts +20 -0
  100. package/dist/eval/fixtures.d.ts.map +1 -1
  101. package/dist/eval/fixtures.js +430 -0
  102. package/dist/eval/fixtures.js.map +1 -1
  103. package/dist/scanners/cache.d.ts.map +1 -1
  104. package/dist/scanners/cache.js +4 -0
  105. package/dist/scanners/cache.js.map +1 -1
  106. package/dist/scanners/dast/index.d.ts +39 -0
  107. package/dist/scanners/dast/index.d.ts.map +1 -0
  108. package/dist/scanners/dast/index.js +259 -0
  109. package/dist/scanners/dast/index.js.map +1 -0
  110. package/dist/scanners/dast/nuclei.d.ts +26 -0
  111. package/dist/scanners/dast/nuclei.d.ts.map +1 -0
  112. package/dist/scanners/dast/nuclei.js +354 -0
  113. package/dist/scanners/dast/nuclei.js.map +1 -0
  114. package/dist/scanners/dast/types.d.ts +306 -0
  115. package/dist/scanners/dast/types.d.ts.map +1 -0
  116. package/dist/scanners/dast/types.js +52 -0
  117. package/dist/scanners/dast/types.js.map +1 -0
  118. package/dist/scanners/dast/zap.d.ts +26 -0
  119. package/dist/scanners/dast/zap.d.ts.map +1 -0
  120. package/dist/scanners/dast/zap.js +453 -0
  121. package/dist/scanners/dast/zap.js.map +1 -0
  122. package/dist/scanners/fp-feedback.d.ts +140 -0
  123. package/dist/scanners/fp-feedback.d.ts.map +1 -0
  124. package/dist/scanners/fp-feedback.js +292 -0
  125. package/dist/scanners/fp-feedback.js.map +1 -0
  126. package/dist/scanners/fp-filter.d.ts +94 -0
  127. package/dist/scanners/fp-filter.d.ts.map +1 -0
  128. package/dist/scanners/fp-filter.js +397 -0
  129. package/dist/scanners/fp-filter.js.map +1 -0
  130. package/dist/scanners/fp-tracker.d.ts +125 -0
  131. package/dist/scanners/fp-tracker.d.ts.map +1 -0
  132. package/dist/scanners/fp-tracker.js +330 -0
  133. package/dist/scanners/fp-tracker.js.map +1 -0
  134. package/dist/scanners/index.d.ts.map +1 -1
  135. package/dist/scanners/index.js +56 -0
  136. package/dist/scanners/index.js.map +1 -1
  137. package/dist/scanners/index.test.js +6 -6
  138. package/dist/scanners/index.test.js.map +1 -1
  139. package/dist/scanners/logic/auth-flow-analyzer.d.ts +18 -0
  140. package/dist/scanners/logic/auth-flow-analyzer.d.ts.map +1 -0
  141. package/dist/scanners/logic/auth-flow-analyzer.js +384 -0
  142. package/dist/scanners/logic/auth-flow-analyzer.js.map +1 -0
  143. package/dist/scanners/logic/endpoint-analyzer.d.ts +29 -0
  144. package/dist/scanners/logic/endpoint-analyzer.d.ts.map +1 -0
  145. package/dist/scanners/logic/endpoint-analyzer.js +528 -0
  146. package/dist/scanners/logic/endpoint-analyzer.js.map +1 -0
  147. package/dist/scanners/logic/index.d.ts +41 -0
  148. package/dist/scanners/logic/index.d.ts.map +1 -0
  149. package/dist/scanners/logic/index.js +268 -0
  150. package/dist/scanners/logic/index.js.map +1 -0
  151. package/dist/scanners/logic/types.d.ts +254 -0
  152. package/dist/scanners/logic/types.d.ts.map +1 -0
  153. package/dist/scanners/logic/types.js +142 -0
  154. package/dist/scanners/logic/types.js.map +1 -0
  155. package/dist/scanners/types.d.ts +1 -1
  156. package/dist/scanners/types.d.ts.map +1 -1
  157. package/dist/scanners/types.js +4 -0
  158. package/dist/scanners/types.js.map +1 -1
  159. package/package.json +5 -3
@@ -0,0 +1,453 @@
1
+ /**
2
+ * OWASP ZAP Scanner Integration
3
+ *
4
+ * Integrates with OWASP ZAP (Zed Attack Proxy) for dynamic
5
+ * application security testing.
6
+ *
7
+ * @module scanners/dast/zap
8
+ */
9
+ import spawn from "cross-spawn";
10
+ import { logger } from "../../logger.js";
11
+ import { ZAP_RISK_MAPPING, ZAP_CONFIDENCE_MAPPING, } from "./types.js";
12
+ /**
13
+ * ZAP API endpoint (default local)
14
+ */
15
+ const ZAP_API_URL = process.env.ZAP_API_URL || "http://localhost:8080";
16
+ const ZAP_API_KEY = process.env.ZAP_API_KEY || "";
17
+ /**
18
+ * Check if ZAP is available
19
+ */
20
+ export async function checkZapAvailable() {
21
+ return new Promise((resolve) => {
22
+ // Try docker first
23
+ const dockerChild = spawn("docker", ["images", "owasp/zap2docker-stable", "--format", "{{.Repository}}"], {
24
+ timeout: 10000,
25
+ });
26
+ let dockerOutput = "";
27
+ dockerChild.stdout?.on("data", (data) => {
28
+ dockerOutput += data.toString();
29
+ });
30
+ dockerChild.on("close", (dockerCode) => {
31
+ if (dockerCode === 0 && dockerOutput.includes("owasp/zap2docker-stable")) {
32
+ resolve({
33
+ scanner: "zap",
34
+ available: true,
35
+ version: "docker",
36
+ path: "docker",
37
+ features: {
38
+ passiveScan: true,
39
+ activeScan: true,
40
+ apiScan: true,
41
+ authentication: true,
42
+ },
43
+ });
44
+ return;
45
+ }
46
+ // Try zap-cli
47
+ const cliChild = spawn("zap-cli", ["--version"], { timeout: 5000 });
48
+ let cliVersion = "";
49
+ cliChild.stdout?.on("data", (data) => {
50
+ cliVersion += data.toString();
51
+ });
52
+ cliChild.on("close", (cliCode) => {
53
+ if (cliCode === 0) {
54
+ resolve({
55
+ scanner: "zap",
56
+ available: true,
57
+ version: cliVersion.trim(),
58
+ path: "zap-cli",
59
+ features: {
60
+ passiveScan: true,
61
+ activeScan: true,
62
+ apiScan: true,
63
+ authentication: true,
64
+ },
65
+ });
66
+ return;
67
+ }
68
+ // Try checking if ZAP API is running
69
+ checkZapApi().then((apiAvailable) => {
70
+ if (apiAvailable) {
71
+ resolve({
72
+ scanner: "zap",
73
+ available: true,
74
+ version: "api",
75
+ path: ZAP_API_URL,
76
+ features: {
77
+ passiveScan: true,
78
+ activeScan: true,
79
+ apiScan: true,
80
+ authentication: true,
81
+ },
82
+ });
83
+ }
84
+ else {
85
+ resolve({
86
+ scanner: "zap",
87
+ available: false,
88
+ error: "ZAP not found. Install via Docker (owasp/zap2docker-stable), zap-cli, or start ZAP with API enabled.",
89
+ });
90
+ }
91
+ });
92
+ });
93
+ cliChild.on("error", () => {
94
+ checkZapApi().then((apiAvailable) => {
95
+ if (apiAvailable) {
96
+ resolve({
97
+ scanner: "zap",
98
+ available: true,
99
+ version: "api",
100
+ path: ZAP_API_URL,
101
+ features: {
102
+ passiveScan: true,
103
+ activeScan: true,
104
+ apiScan: true,
105
+ authentication: true,
106
+ },
107
+ });
108
+ }
109
+ else {
110
+ resolve({
111
+ scanner: "zap",
112
+ available: false,
113
+ error: "ZAP not found. Install via Docker (owasp/zap2docker-stable), zap-cli, or start ZAP with API enabled.",
114
+ });
115
+ }
116
+ });
117
+ });
118
+ });
119
+ dockerChild.on("error", () => {
120
+ // Docker not available, try other methods
121
+ const cliChild = spawn("zap-cli", ["--version"], { timeout: 5000 });
122
+ cliChild.on("close", (code) => {
123
+ if (code === 0) {
124
+ resolve({
125
+ scanner: "zap",
126
+ available: true,
127
+ path: "zap-cli",
128
+ features: {
129
+ passiveScan: true,
130
+ activeScan: true,
131
+ apiScan: true,
132
+ authentication: true,
133
+ },
134
+ });
135
+ }
136
+ else {
137
+ resolve({
138
+ scanner: "zap",
139
+ available: false,
140
+ error: "ZAP not found",
141
+ });
142
+ }
143
+ });
144
+ cliChild.on("error", () => {
145
+ resolve({
146
+ scanner: "zap",
147
+ available: false,
148
+ error: "ZAP not found",
149
+ });
150
+ });
151
+ });
152
+ });
153
+ }
154
+ /**
155
+ * Check if ZAP API is running
156
+ */
157
+ async function checkZapApi() {
158
+ try {
159
+ const url = `${ZAP_API_URL}/JSON/core/view/version/?apikey=${ZAP_API_KEY}`;
160
+ const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
161
+ return response.ok;
162
+ }
163
+ catch {
164
+ return false;
165
+ }
166
+ }
167
+ /**
168
+ * Run ZAP scan using Docker
169
+ */
170
+ async function runZapDocker(target, policy) {
171
+ return new Promise((resolve) => {
172
+ const args = [
173
+ "run",
174
+ "--rm",
175
+ "-t",
176
+ ];
177
+ // Add network host for local targets
178
+ if (target.url.includes("localhost") || target.url.includes("127.0.0.1")) {
179
+ args.push("--network", "host");
180
+ }
181
+ args.push("owasp/zap2docker-stable");
182
+ // Choose scan type based on policy
183
+ if (policy.passiveOnly) {
184
+ args.push("zap-baseline.py");
185
+ }
186
+ else {
187
+ args.push("zap-full-scan.py");
188
+ }
189
+ args.push("-t", target.url);
190
+ args.push("-J", "zap-report.json"); // JSON output
191
+ args.push("-I"); // Don't fail on warnings
192
+ if (policy.maxDuration) {
193
+ args.push("-m", String(Math.floor(policy.maxDuration / 60))); // Minutes
194
+ }
195
+ if (policy.ajaxSpider) {
196
+ args.push("-j"); // Enable AJAX spider
197
+ }
198
+ logger.info("zap.docker_scan", { target: target.url, passiveOnly: policy.passiveOnly });
199
+ const child = spawn("docker", args, {
200
+ timeout: (policy.maxDuration || 300) * 1000 + 60000, // Add 1 min buffer
201
+ });
202
+ let stdout = "";
203
+ let stderr = "";
204
+ child.stdout?.on("data", (data) => {
205
+ stdout += data.toString();
206
+ });
207
+ child.stderr?.on("data", (data) => {
208
+ stderr += data.toString();
209
+ });
210
+ child.on("close", (code) => {
211
+ // ZAP returns non-zero for warnings, which is OK
212
+ resolve({
213
+ success: code === 0 || code === 1 || code === 2,
214
+ output: stdout,
215
+ error: code !== 0 && code !== 1 && code !== 2 ? stderr : undefined,
216
+ });
217
+ });
218
+ child.on("error", (error) => {
219
+ resolve({
220
+ success: false,
221
+ output: stdout,
222
+ error: String(error),
223
+ });
224
+ });
225
+ });
226
+ }
227
+ /**
228
+ * Run ZAP scan via API
229
+ */
230
+ async function runZapApi(target, policy) {
231
+ try {
232
+ const baseUrl = ZAP_API_URL;
233
+ const apiKey = ZAP_API_KEY;
234
+ // Start spider
235
+ logger.info("zap.api_spider", { target: target.url });
236
+ const spiderResponse = await fetch(`${baseUrl}/JSON/spider/action/scan/?apikey=${apiKey}&url=${encodeURIComponent(target.url)}&maxChildren=${policy.maxChildren || 10}&recurse=true`, { signal: AbortSignal.timeout(30000) });
237
+ if (!spiderResponse.ok) {
238
+ throw new Error(`Spider failed: ${spiderResponse.statusText}`);
239
+ }
240
+ const spiderResult = await spiderResponse.json();
241
+ const scanId = spiderResult.scan;
242
+ // Wait for spider to complete
243
+ let spiderStatus = "0";
244
+ const startTime = Date.now();
245
+ const maxWait = (policy.maxDuration || 300) * 1000;
246
+ while (spiderStatus !== "100" && Date.now() - startTime < maxWait) {
247
+ await new Promise((r) => setTimeout(r, 2000));
248
+ const statusResponse = await fetch(`${baseUrl}/JSON/spider/view/status/?apikey=${apiKey}&scanId=${scanId}`);
249
+ const statusResult = await statusResponse.json();
250
+ spiderStatus = statusResult.status;
251
+ }
252
+ // Run passive scan (always)
253
+ logger.info("zap.api_passive_scan", { target: target.url });
254
+ // Wait for passive scan
255
+ let pscanRecords = "1";
256
+ while (pscanRecords !== "0" && Date.now() - startTime < maxWait) {
257
+ await new Promise((r) => setTimeout(r, 2000));
258
+ const pscanResponse = await fetch(`${baseUrl}/JSON/pscan/view/recordsToScan/?apikey=${apiKey}`);
259
+ const pscanResult = await pscanResponse.json();
260
+ pscanRecords = pscanResult.recordsToScan;
261
+ }
262
+ // Run active scan if not passive-only
263
+ if (!policy.passiveOnly) {
264
+ logger.info("zap.api_active_scan", { target: target.url });
265
+ const ascanResponse = await fetch(`${baseUrl}/JSON/ascan/action/scan/?apikey=${apiKey}&url=${encodeURIComponent(target.url)}&recurse=true&scanPolicyName=${policy.zapPolicy || ""}`, { signal: AbortSignal.timeout(30000) });
266
+ if (ascanResponse.ok) {
267
+ const ascanResult = await ascanResponse.json();
268
+ const ascanId = ascanResult.scan;
269
+ // Wait for active scan
270
+ let ascanStatus = "0";
271
+ while (ascanStatus !== "100" && Date.now() - startTime < maxWait) {
272
+ await new Promise((r) => setTimeout(r, 5000));
273
+ const statusResponse = await fetch(`${baseUrl}/JSON/ascan/view/status/?apikey=${apiKey}&scanId=${ascanId}`);
274
+ const statusResult = await statusResponse.json();
275
+ ascanStatus = statusResult.status;
276
+ }
277
+ }
278
+ }
279
+ // Get alerts
280
+ const alertsResponse = await fetch(`${baseUrl}/JSON/core/view/alerts/?apikey=${apiKey}&baseurl=${encodeURIComponent(target.url)}&start=0&count=1000`);
281
+ const alertsResult = await alertsResponse.json();
282
+ return {
283
+ success: true,
284
+ alerts: alertsResult.alerts || [],
285
+ };
286
+ }
287
+ catch (error) {
288
+ return {
289
+ success: false,
290
+ alerts: [],
291
+ error: String(error),
292
+ };
293
+ }
294
+ }
295
+ /**
296
+ * Parse ZAP JSON output to DASTFinding
297
+ */
298
+ export function parseZapAlerts(alerts) {
299
+ return alerts.map((alert) => ({
300
+ scanner: "zap",
301
+ ruleId: `zap-${alert.pluginId}`,
302
+ name: alert.name || alert.alert,
303
+ description: alert.description,
304
+ severity: ZAP_RISK_MAPPING[alert.risk] || "info",
305
+ confidence: ZAP_CONFIDENCE_MAPPING[alert.confidence] || 50,
306
+ url: alert.url,
307
+ method: alert.method,
308
+ parameter: alert.param,
309
+ evidence: alert.evidence,
310
+ attack: alert.attack,
311
+ cweIds: alert.cweid ? [`CWE-${alert.cweid}`] : undefined,
312
+ references: alert.reference ? alert.reference.split("\n").filter(Boolean) : undefined,
313
+ solution: alert.solution,
314
+ tags: Object.keys(alert.tags || {}),
315
+ timestamp: new Date().toISOString(),
316
+ rawOutput: alert,
317
+ }));
318
+ }
319
+ /**
320
+ * Run ZAP scan
321
+ */
322
+ export async function runZap(target, policy = {}) {
323
+ const startTime = new Date();
324
+ const mergedPolicy = { ...{ passiveOnly: true, maxDuration: 300 }, ...policy };
325
+ logger.info("zap.scan_start", {
326
+ target: target.url,
327
+ passiveOnly: mergedPolicy.passiveOnly,
328
+ });
329
+ // Check availability
330
+ const availability = await checkZapAvailable();
331
+ if (!availability.available) {
332
+ return {
333
+ scanner: "zap",
334
+ target,
335
+ findings: [],
336
+ duration: Date.now() - startTime.getTime(),
337
+ success: false,
338
+ error: availability.error || "ZAP not available",
339
+ stats: {
340
+ requestCount: 0,
341
+ urlsDiscovered: 0,
342
+ uniqueFindings: 0,
343
+ bySeverity: {},
344
+ },
345
+ startTime: startTime.toISOString(),
346
+ endTime: new Date().toISOString(),
347
+ policy: mergedPolicy,
348
+ };
349
+ }
350
+ let findings = [];
351
+ let success = false;
352
+ let error;
353
+ // Run scan based on available method
354
+ if (availability.path === "docker") {
355
+ const result = await runZapDocker(target, mergedPolicy);
356
+ success = result.success;
357
+ error = result.error;
358
+ // Parse JSON output if available
359
+ if (result.output) {
360
+ try {
361
+ // Try to extract JSON from output
362
+ const jsonMatch = result.output.match(/\{[\s\S]*"alerts"[\s\S]*\}/);
363
+ if (jsonMatch) {
364
+ const parsed = JSON.parse(jsonMatch[0]);
365
+ if (parsed.site?.[0]?.alerts) {
366
+ findings = parseZapAlerts(parsed.site[0].alerts);
367
+ }
368
+ }
369
+ }
370
+ catch {
371
+ // JSON parsing failed, try line-by-line parsing
372
+ logger.debug("zap.parse_failed", { output: result.output.slice(0, 500) });
373
+ }
374
+ }
375
+ }
376
+ else if (availability.path === ZAP_API_URL || availability.version === "api") {
377
+ const result = await runZapApi(target, mergedPolicy);
378
+ success = result.success;
379
+ error = result.error;
380
+ findings = parseZapAlerts(result.alerts);
381
+ }
382
+ else {
383
+ // zap-cli not fully implemented, fallback to API check
384
+ const apiResult = await runZapApi(target, mergedPolicy);
385
+ success = apiResult.success;
386
+ error = apiResult.error;
387
+ findings = parseZapAlerts(apiResult.alerts);
388
+ }
389
+ const endTime = new Date();
390
+ // Calculate stats
391
+ const bySeverity = {};
392
+ for (const finding of findings) {
393
+ bySeverity[finding.severity] = (bySeverity[finding.severity] || 0) + 1;
394
+ }
395
+ const result = {
396
+ scanner: "zap",
397
+ target,
398
+ findings,
399
+ duration: endTime.getTime() - startTime.getTime(),
400
+ success,
401
+ error,
402
+ stats: {
403
+ requestCount: 0, // Not available from ZAP output
404
+ urlsDiscovered: new Set(findings.map((f) => f.url)).size,
405
+ uniqueFindings: findings.length,
406
+ bySeverity,
407
+ },
408
+ version: availability.version,
409
+ startTime: startTime.toISOString(),
410
+ endTime: endTime.toISOString(),
411
+ policy: mergedPolicy,
412
+ };
413
+ logger.info("zap.scan_complete", {
414
+ findings: findings.length,
415
+ duration: result.duration,
416
+ success,
417
+ });
418
+ return result;
419
+ }
420
+ /**
421
+ * Get ZAP installation instructions
422
+ */
423
+ export function getZapInstallInstructions() {
424
+ return `
425
+ # OWASP ZAP Installation
426
+
427
+ ## Docker (Recommended)
428
+ \`\`\`bash
429
+ docker pull owasp/zap2docker-stable
430
+ \`\`\`
431
+
432
+ ## macOS
433
+ \`\`\`bash
434
+ brew install --cask owasp-zap
435
+ \`\`\`
436
+
437
+ ## Linux
438
+ \`\`\`bash
439
+ # Download from https://www.zaproxy.org/download/
440
+ wget https://github.com/zaproxy/zaproxy/releases/download/v2.14.0/ZAP_2.14.0_Linux.tar.gz
441
+ tar -xzf ZAP_2.14.0_Linux.tar.gz
442
+ \`\`\`
443
+
444
+ ## Windows
445
+ Download installer from https://www.zaproxy.org/download/
446
+
447
+ ## Start ZAP with API
448
+ \`\`\`bash
449
+ zap.sh -daemon -port 8080 -config api.key=your-api-key
450
+ \`\`\`
451
+ `;
452
+ }
453
+ //# sourceMappingURL=zap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zap.js","sourceRoot":"","sources":["../../../src/scanners/dast/zap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * False Positive Feedback
3
+ *
4
+ * Handles user feedback on findings and maintains a feedback database
5
+ * for improving FP detection over time.
6
+ *
7
+ * @module scanners/fp-feedback
8
+ */
9
+ import type { ScannerType, DeterministicFinding } from "./types.js";
10
+ import type { Severity } from "../certification/types.js";
11
+ /**
12
+ * Reason for marking a finding as FP
13
+ */
14
+ export type FPReason = "test-code" | "false-pattern-match" | "sanitized-elsewhere" | "intentional" | "vendor-code" | "generated-code" | "example-code" | "configuration" | "other";
15
+ /**
16
+ * FP reason descriptions for UI
17
+ */
18
+ export declare const FP_REASON_DESCRIPTIONS: Record<FPReason, string>;
19
+ /**
20
+ * A single feedback entry
21
+ */
22
+ export interface FeedbackEntry {
23
+ /** Unique feedback ID */
24
+ id: string;
25
+ /** Finding ID this feedback relates to */
26
+ findingId: string;
27
+ /** Scanner that generated the finding */
28
+ scanner: ScannerType;
29
+ /** Rule ID */
30
+ ruleId: string;
31
+ /** File path */
32
+ file: string;
33
+ /** Line number */
34
+ line?: number;
35
+ /** Original severity */
36
+ severity: Severity;
37
+ /** Verdict: true positive or false positive */
38
+ verdict: "tp" | "fp";
39
+ /** Reason for FP (if verdict is FP) */
40
+ reason?: FPReason;
41
+ /** Additional details/notes */
42
+ details?: string;
43
+ /** Who submitted the feedback */
44
+ submittedBy?: string;
45
+ /** When the feedback was submitted */
46
+ submittedAt: string;
47
+ /** Hash of the code at feedback time (for invalidation) */
48
+ codeHash?: string;
49
+ }
50
+ /**
51
+ * Feedback database
52
+ */
53
+ export interface FeedbackDatabase {
54
+ version: string;
55
+ projectPath: string;
56
+ entries: FeedbackEntry[];
57
+ stats: {
58
+ totalFeedback: number;
59
+ tpCount: number;
60
+ fpCount: number;
61
+ byScanner: Record<string, {
62
+ tp: number;
63
+ fp: number;
64
+ }>;
65
+ byReason: Record<string, number>;
66
+ };
67
+ }
68
+ /**
69
+ * Load feedback database
70
+ */
71
+ export declare function loadFeedbackDatabase(projectPath: string): Promise<FeedbackDatabase>;
72
+ /**
73
+ * Save feedback database
74
+ */
75
+ export declare function saveFeedbackDatabase(projectPath: string, db: FeedbackDatabase): Promise<void>;
76
+ /**
77
+ * Submit feedback for a finding
78
+ */
79
+ export declare function submitFeedback(projectPath: string, finding: DeterministicFinding, verdict: "tp" | "fp", options?: {
80
+ reason?: FPReason;
81
+ details?: string;
82
+ submittedBy?: string;
83
+ codeHash?: string;
84
+ }): Promise<FeedbackEntry>;
85
+ /**
86
+ * Get feedback for a specific finding
87
+ */
88
+ export declare function getFeedbackForFinding(projectPath: string, scanner: ScannerType, ruleId: string, file: string, line?: number): Promise<FeedbackEntry[]>;
89
+ /**
90
+ * Get all feedback for a rule
91
+ */
92
+ export declare function getFeedbackForRule(projectPath: string, scanner: ScannerType, ruleId: string): Promise<FeedbackEntry[]>;
93
+ /**
94
+ * Check if a finding has existing feedback
95
+ */
96
+ export declare function hasFeedback(projectPath: string, scanner: ScannerType, ruleId: string, file: string, line?: number): Promise<boolean>;
97
+ /**
98
+ * Get suppression suggestions based on feedback
99
+ */
100
+ export declare function getSuppressionSuggestions(projectPath: string, options?: {
101
+ minFPRate?: number;
102
+ minSampleSize?: number;
103
+ }): Promise<Array<{
104
+ scanner: ScannerType;
105
+ ruleId: string;
106
+ fpRate: number;
107
+ sampleSize: number;
108
+ suggestion: "disable" | "review" | "keep";
109
+ commonReasons: FPReason[];
110
+ }>>;
111
+ /**
112
+ * Generate feedback summary report
113
+ */
114
+ export declare function generateFeedbackReport(projectPath: string): Promise<{
115
+ overview: {
116
+ totalFeedback: number;
117
+ tpCount: number;
118
+ fpCount: number;
119
+ overallFPRate: number;
120
+ };
121
+ byScanner: Array<{
122
+ scanner: ScannerType;
123
+ total: number;
124
+ tp: number;
125
+ fp: number;
126
+ fpRate: number;
127
+ }>;
128
+ topFPReasons: Array<{
129
+ reason: FPReason;
130
+ count: number;
131
+ percentage: number;
132
+ }>;
133
+ recentFeedback: FeedbackEntry[];
134
+ suppressionSuggestions: Awaited<ReturnType<typeof getSuppressionSuggestions>>;
135
+ }>;
136
+ /**
137
+ * Clear old feedback entries
138
+ */
139
+ export declare function pruneOldFeedback(projectPath: string, maxAgeDays?: number): Promise<number>;
140
+ //# sourceMappingURL=fp-feedback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fp-feedback.d.ts","sourceRoot":"","sources":["../../src/scanners/fp-feedback.ts"],"names":[],"mappings":"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"}