@vulcn/engine 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/dist/index.cjs +707 -363
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +663 -148
- package/dist/index.d.ts +663 -148
- package/dist/index.js +685 -355
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,479 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Vulcn Project Configuration — `.vulcn.yml` schema
|
|
5
|
+
*
|
|
6
|
+
* Single source of truth for all Vulcn configuration.
|
|
7
|
+
* The CLI is a thin layer that passes this config to the engine.
|
|
8
|
+
* Plugin names never appear here — the engine maps flat keys to plugins internally.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
declare const VulcnProjectConfigSchema: z.ZodObject<{
|
|
12
|
+
/** Target URL to scan */
|
|
13
|
+
target: z.ZodOptional<z.ZodString>;
|
|
14
|
+
/** Scan settings (browser, headless, timeout) */
|
|
15
|
+
scan: z.ZodDefault<z.ZodObject<{
|
|
16
|
+
/** Browser engine to use */
|
|
17
|
+
browser: z.ZodDefault<z.ZodEnum<["chromium", "firefox", "webkit"]>>;
|
|
18
|
+
/** Run in headless mode */
|
|
19
|
+
headless: z.ZodDefault<z.ZodBoolean>;
|
|
20
|
+
/** Per-step timeout in ms */
|
|
21
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
22
|
+
}, "strip", z.ZodTypeAny, {
|
|
23
|
+
browser: "chromium" | "firefox" | "webkit";
|
|
24
|
+
headless: boolean;
|
|
25
|
+
timeout: number;
|
|
26
|
+
}, {
|
|
27
|
+
browser?: "chromium" | "firefox" | "webkit" | undefined;
|
|
28
|
+
headless?: boolean | undefined;
|
|
29
|
+
timeout?: number | undefined;
|
|
30
|
+
}>>;
|
|
31
|
+
/** Payload configuration */
|
|
32
|
+
payloads: z.ZodDefault<z.ZodObject<{
|
|
33
|
+
/** Payload types to use */
|
|
34
|
+
types: z.ZodDefault<z.ZodArray<z.ZodEnum<["xss", "sqli", "xxe", "cmd", "redirect", "traversal"]>, "many">>;
|
|
35
|
+
/** Opt-in to PayloadsAllTheThings community payloads */
|
|
36
|
+
payloadbox: z.ZodDefault<z.ZodBoolean>;
|
|
37
|
+
/** Max payloads per type from PayloadBox */
|
|
38
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
39
|
+
/** Path to custom payload YAML file (relative to project root) */
|
|
40
|
+
custom: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
41
|
+
}, "strip", z.ZodTypeAny, {
|
|
42
|
+
custom: string | null;
|
|
43
|
+
types: ("xss" | "sqli" | "xxe" | "cmd" | "redirect" | "traversal")[];
|
|
44
|
+
payloadbox: boolean;
|
|
45
|
+
limit: number;
|
|
46
|
+
}, {
|
|
47
|
+
custom?: string | null | undefined;
|
|
48
|
+
types?: ("xss" | "sqli" | "xxe" | "cmd" | "redirect" | "traversal")[] | undefined;
|
|
49
|
+
payloadbox?: boolean | undefined;
|
|
50
|
+
limit?: number | undefined;
|
|
51
|
+
}>>;
|
|
52
|
+
/** Detection configuration */
|
|
53
|
+
detection: z.ZodDefault<z.ZodObject<{
|
|
54
|
+
/** XSS detection settings */
|
|
55
|
+
xss: z.ZodDefault<z.ZodObject<{
|
|
56
|
+
/** Monitor alert/confirm/prompt dialogs */
|
|
57
|
+
dialogs: z.ZodDefault<z.ZodBoolean>;
|
|
58
|
+
/** Monitor console.log markers */
|
|
59
|
+
console: z.ZodDefault<z.ZodBoolean>;
|
|
60
|
+
/** Console marker prefix */
|
|
61
|
+
consoleMarker: z.ZodDefault<z.ZodString>;
|
|
62
|
+
/** Check for injected <script> elements */
|
|
63
|
+
domMutation: z.ZodDefault<z.ZodBoolean>;
|
|
64
|
+
/** Finding severity level */
|
|
65
|
+
severity: z.ZodDefault<z.ZodEnum<["critical", "high", "medium", "low"]>>;
|
|
66
|
+
/** Text patterns to match in alert messages */
|
|
67
|
+
alertPatterns: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
68
|
+
}, "strip", z.ZodTypeAny, {
|
|
69
|
+
dialogs: boolean;
|
|
70
|
+
console: boolean;
|
|
71
|
+
consoleMarker: string;
|
|
72
|
+
domMutation: boolean;
|
|
73
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
74
|
+
alertPatterns: string[];
|
|
75
|
+
}, {
|
|
76
|
+
dialogs?: boolean | undefined;
|
|
77
|
+
console?: boolean | undefined;
|
|
78
|
+
consoleMarker?: string | undefined;
|
|
79
|
+
domMutation?: boolean | undefined;
|
|
80
|
+
severity?: "critical" | "high" | "medium" | "low" | undefined;
|
|
81
|
+
alertPatterns?: string[] | undefined;
|
|
82
|
+
}>>;
|
|
83
|
+
/** Reflection detection settings */
|
|
84
|
+
reflection: z.ZodDefault<z.ZodObject<{
|
|
85
|
+
/** Enable reflection detection */
|
|
86
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
87
|
+
/** Minimum payload length to check */
|
|
88
|
+
minLength: z.ZodDefault<z.ZodNumber>;
|
|
89
|
+
/** Which HTML contexts to check for reflections */
|
|
90
|
+
contexts: z.ZodDefault<z.ZodObject<{
|
|
91
|
+
script: z.ZodDefault<z.ZodBoolean>;
|
|
92
|
+
attribute: z.ZodDefault<z.ZodBoolean>;
|
|
93
|
+
body: z.ZodDefault<z.ZodBoolean>;
|
|
94
|
+
}, "strip", z.ZodTypeAny, {
|
|
95
|
+
script: boolean;
|
|
96
|
+
attribute: boolean;
|
|
97
|
+
body: boolean;
|
|
98
|
+
}, {
|
|
99
|
+
script?: boolean | undefined;
|
|
100
|
+
attribute?: boolean | undefined;
|
|
101
|
+
body?: boolean | undefined;
|
|
102
|
+
}>>;
|
|
103
|
+
/** Severity per context */
|
|
104
|
+
severity: z.ZodDefault<z.ZodObject<{
|
|
105
|
+
script: z.ZodDefault<z.ZodEnum<["critical", "high", "medium", "low"]>>;
|
|
106
|
+
attribute: z.ZodDefault<z.ZodEnum<["critical", "high", "medium", "low"]>>;
|
|
107
|
+
body: z.ZodDefault<z.ZodEnum<["critical", "high", "medium", "low"]>>;
|
|
108
|
+
}, "strip", z.ZodTypeAny, {
|
|
109
|
+
script: "critical" | "high" | "medium" | "low";
|
|
110
|
+
attribute: "critical" | "high" | "medium" | "low";
|
|
111
|
+
body: "critical" | "high" | "medium" | "low";
|
|
112
|
+
}, {
|
|
113
|
+
script?: "critical" | "high" | "medium" | "low" | undefined;
|
|
114
|
+
attribute?: "critical" | "high" | "medium" | "low" | undefined;
|
|
115
|
+
body?: "critical" | "high" | "medium" | "low" | undefined;
|
|
116
|
+
}>>;
|
|
117
|
+
}, "strip", z.ZodTypeAny, {
|
|
118
|
+
severity: {
|
|
119
|
+
script: "critical" | "high" | "medium" | "low";
|
|
120
|
+
attribute: "critical" | "high" | "medium" | "low";
|
|
121
|
+
body: "critical" | "high" | "medium" | "low";
|
|
122
|
+
};
|
|
123
|
+
enabled: boolean;
|
|
124
|
+
minLength: number;
|
|
125
|
+
contexts: {
|
|
126
|
+
script: boolean;
|
|
127
|
+
attribute: boolean;
|
|
128
|
+
body: boolean;
|
|
129
|
+
};
|
|
130
|
+
}, {
|
|
131
|
+
severity?: {
|
|
132
|
+
script?: "critical" | "high" | "medium" | "low" | undefined;
|
|
133
|
+
attribute?: "critical" | "high" | "medium" | "low" | undefined;
|
|
134
|
+
body?: "critical" | "high" | "medium" | "low" | undefined;
|
|
135
|
+
} | undefined;
|
|
136
|
+
enabled?: boolean | undefined;
|
|
137
|
+
minLength?: number | undefined;
|
|
138
|
+
contexts?: {
|
|
139
|
+
script?: boolean | undefined;
|
|
140
|
+
attribute?: boolean | undefined;
|
|
141
|
+
body?: boolean | undefined;
|
|
142
|
+
} | undefined;
|
|
143
|
+
}>>;
|
|
144
|
+
/** Enable passive security checks (headers, cookies, info-disclosure) */
|
|
145
|
+
passive: z.ZodDefault<z.ZodBoolean>;
|
|
146
|
+
}, "strip", z.ZodTypeAny, {
|
|
147
|
+
xss: {
|
|
148
|
+
dialogs: boolean;
|
|
149
|
+
console: boolean;
|
|
150
|
+
consoleMarker: string;
|
|
151
|
+
domMutation: boolean;
|
|
152
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
153
|
+
alertPatterns: string[];
|
|
154
|
+
};
|
|
155
|
+
reflection: {
|
|
156
|
+
severity: {
|
|
157
|
+
script: "critical" | "high" | "medium" | "low";
|
|
158
|
+
attribute: "critical" | "high" | "medium" | "low";
|
|
159
|
+
body: "critical" | "high" | "medium" | "low";
|
|
160
|
+
};
|
|
161
|
+
enabled: boolean;
|
|
162
|
+
minLength: number;
|
|
163
|
+
contexts: {
|
|
164
|
+
script: boolean;
|
|
165
|
+
attribute: boolean;
|
|
166
|
+
body: boolean;
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
passive: boolean;
|
|
170
|
+
}, {
|
|
171
|
+
xss?: {
|
|
172
|
+
dialogs?: boolean | undefined;
|
|
173
|
+
console?: boolean | undefined;
|
|
174
|
+
consoleMarker?: string | undefined;
|
|
175
|
+
domMutation?: boolean | undefined;
|
|
176
|
+
severity?: "critical" | "high" | "medium" | "low" | undefined;
|
|
177
|
+
alertPatterns?: string[] | undefined;
|
|
178
|
+
} | undefined;
|
|
179
|
+
reflection?: {
|
|
180
|
+
severity?: {
|
|
181
|
+
script?: "critical" | "high" | "medium" | "low" | undefined;
|
|
182
|
+
attribute?: "critical" | "high" | "medium" | "low" | undefined;
|
|
183
|
+
body?: "critical" | "high" | "medium" | "low" | undefined;
|
|
184
|
+
} | undefined;
|
|
185
|
+
enabled?: boolean | undefined;
|
|
186
|
+
minLength?: number | undefined;
|
|
187
|
+
contexts?: {
|
|
188
|
+
script?: boolean | undefined;
|
|
189
|
+
attribute?: boolean | undefined;
|
|
190
|
+
body?: boolean | undefined;
|
|
191
|
+
} | undefined;
|
|
192
|
+
} | undefined;
|
|
193
|
+
passive?: boolean | undefined;
|
|
194
|
+
}>>;
|
|
195
|
+
/** Crawl configuration */
|
|
196
|
+
crawl: z.ZodDefault<z.ZodObject<{
|
|
197
|
+
/** Maximum crawl depth */
|
|
198
|
+
depth: z.ZodDefault<z.ZodNumber>;
|
|
199
|
+
/** Maximum pages to visit */
|
|
200
|
+
maxPages: z.ZodDefault<z.ZodNumber>;
|
|
201
|
+
/** Stay on same origin */
|
|
202
|
+
sameOrigin: z.ZodDefault<z.ZodBoolean>;
|
|
203
|
+
/** Per-page timeout in ms */
|
|
204
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
205
|
+
}, "strip", z.ZodTypeAny, {
|
|
206
|
+
timeout: number;
|
|
207
|
+
depth: number;
|
|
208
|
+
maxPages: number;
|
|
209
|
+
sameOrigin: boolean;
|
|
210
|
+
}, {
|
|
211
|
+
timeout?: number | undefined;
|
|
212
|
+
depth?: number | undefined;
|
|
213
|
+
maxPages?: number | undefined;
|
|
214
|
+
sameOrigin?: boolean | undefined;
|
|
215
|
+
}>>;
|
|
216
|
+
/** Report configuration */
|
|
217
|
+
report: z.ZodDefault<z.ZodObject<{
|
|
218
|
+
/** Report format to generate */
|
|
219
|
+
format: z.ZodDefault<z.ZodNullable<z.ZodEnum<["html", "json", "yaml", "sarif", "all"]>>>;
|
|
220
|
+
}, "strip", z.ZodTypeAny, {
|
|
221
|
+
format: "html" | "json" | "yaml" | "sarif" | "all" | null;
|
|
222
|
+
}, {
|
|
223
|
+
format?: "html" | "json" | "yaml" | "sarif" | "all" | null | undefined;
|
|
224
|
+
}>>;
|
|
225
|
+
/** Authentication configuration */
|
|
226
|
+
auth: z.ZodDefault<z.ZodNullable<z.ZodDiscriminatedUnion<"strategy", [z.ZodObject<{
|
|
227
|
+
strategy: z.ZodLiteral<"form">;
|
|
228
|
+
/** Login page URL */
|
|
229
|
+
loginUrl: z.ZodOptional<z.ZodString>;
|
|
230
|
+
/** CSS selector for username field */
|
|
231
|
+
userSelector: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
232
|
+
/** CSS selector for password field */
|
|
233
|
+
passSelector: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
234
|
+
}, "strip", z.ZodTypeAny, {
|
|
235
|
+
strategy: "form";
|
|
236
|
+
userSelector: string | null;
|
|
237
|
+
passSelector: string | null;
|
|
238
|
+
loginUrl?: string | undefined;
|
|
239
|
+
}, {
|
|
240
|
+
strategy: "form";
|
|
241
|
+
loginUrl?: string | undefined;
|
|
242
|
+
userSelector?: string | null | undefined;
|
|
243
|
+
passSelector?: string | null | undefined;
|
|
244
|
+
}>, z.ZodObject<{
|
|
245
|
+
strategy: z.ZodLiteral<"header">;
|
|
246
|
+
/** Headers to include in requests */
|
|
247
|
+
headers: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
248
|
+
}, "strip", z.ZodTypeAny, {
|
|
249
|
+
strategy: "header";
|
|
250
|
+
headers: Record<string, string>;
|
|
251
|
+
}, {
|
|
252
|
+
strategy: "header";
|
|
253
|
+
headers: Record<string, string>;
|
|
254
|
+
}>]>>>;
|
|
255
|
+
}, "strip", z.ZodTypeAny, {
|
|
256
|
+
scan: {
|
|
257
|
+
browser: "chromium" | "firefox" | "webkit";
|
|
258
|
+
headless: boolean;
|
|
259
|
+
timeout: number;
|
|
260
|
+
};
|
|
261
|
+
payloads: {
|
|
262
|
+
custom: string | null;
|
|
263
|
+
types: ("xss" | "sqli" | "xxe" | "cmd" | "redirect" | "traversal")[];
|
|
264
|
+
payloadbox: boolean;
|
|
265
|
+
limit: number;
|
|
266
|
+
};
|
|
267
|
+
detection: {
|
|
268
|
+
xss: {
|
|
269
|
+
dialogs: boolean;
|
|
270
|
+
console: boolean;
|
|
271
|
+
consoleMarker: string;
|
|
272
|
+
domMutation: boolean;
|
|
273
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
274
|
+
alertPatterns: string[];
|
|
275
|
+
};
|
|
276
|
+
reflection: {
|
|
277
|
+
severity: {
|
|
278
|
+
script: "critical" | "high" | "medium" | "low";
|
|
279
|
+
attribute: "critical" | "high" | "medium" | "low";
|
|
280
|
+
body: "critical" | "high" | "medium" | "low";
|
|
281
|
+
};
|
|
282
|
+
enabled: boolean;
|
|
283
|
+
minLength: number;
|
|
284
|
+
contexts: {
|
|
285
|
+
script: boolean;
|
|
286
|
+
attribute: boolean;
|
|
287
|
+
body: boolean;
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
passive: boolean;
|
|
291
|
+
};
|
|
292
|
+
crawl: {
|
|
293
|
+
timeout: number;
|
|
294
|
+
depth: number;
|
|
295
|
+
maxPages: number;
|
|
296
|
+
sameOrigin: boolean;
|
|
297
|
+
};
|
|
298
|
+
report: {
|
|
299
|
+
format: "html" | "json" | "yaml" | "sarif" | "all" | null;
|
|
300
|
+
};
|
|
301
|
+
auth: {
|
|
302
|
+
strategy: "form";
|
|
303
|
+
userSelector: string | null;
|
|
304
|
+
passSelector: string | null;
|
|
305
|
+
loginUrl?: string | undefined;
|
|
306
|
+
} | {
|
|
307
|
+
strategy: "header";
|
|
308
|
+
headers: Record<string, string>;
|
|
309
|
+
} | null;
|
|
310
|
+
target?: string | undefined;
|
|
311
|
+
}, {
|
|
312
|
+
target?: string | undefined;
|
|
313
|
+
scan?: {
|
|
314
|
+
browser?: "chromium" | "firefox" | "webkit" | undefined;
|
|
315
|
+
headless?: boolean | undefined;
|
|
316
|
+
timeout?: number | undefined;
|
|
317
|
+
} | undefined;
|
|
318
|
+
payloads?: {
|
|
319
|
+
custom?: string | null | undefined;
|
|
320
|
+
types?: ("xss" | "sqli" | "xxe" | "cmd" | "redirect" | "traversal")[] | undefined;
|
|
321
|
+
payloadbox?: boolean | undefined;
|
|
322
|
+
limit?: number | undefined;
|
|
323
|
+
} | undefined;
|
|
324
|
+
detection?: {
|
|
325
|
+
xss?: {
|
|
326
|
+
dialogs?: boolean | undefined;
|
|
327
|
+
console?: boolean | undefined;
|
|
328
|
+
consoleMarker?: string | undefined;
|
|
329
|
+
domMutation?: boolean | undefined;
|
|
330
|
+
severity?: "critical" | "high" | "medium" | "low" | undefined;
|
|
331
|
+
alertPatterns?: string[] | undefined;
|
|
332
|
+
} | undefined;
|
|
333
|
+
reflection?: {
|
|
334
|
+
severity?: {
|
|
335
|
+
script?: "critical" | "high" | "medium" | "low" | undefined;
|
|
336
|
+
attribute?: "critical" | "high" | "medium" | "low" | undefined;
|
|
337
|
+
body?: "critical" | "high" | "medium" | "low" | undefined;
|
|
338
|
+
} | undefined;
|
|
339
|
+
enabled?: boolean | undefined;
|
|
340
|
+
minLength?: number | undefined;
|
|
341
|
+
contexts?: {
|
|
342
|
+
script?: boolean | undefined;
|
|
343
|
+
attribute?: boolean | undefined;
|
|
344
|
+
body?: boolean | undefined;
|
|
345
|
+
} | undefined;
|
|
346
|
+
} | undefined;
|
|
347
|
+
passive?: boolean | undefined;
|
|
348
|
+
} | undefined;
|
|
349
|
+
crawl?: {
|
|
350
|
+
timeout?: number | undefined;
|
|
351
|
+
depth?: number | undefined;
|
|
352
|
+
maxPages?: number | undefined;
|
|
353
|
+
sameOrigin?: boolean | undefined;
|
|
354
|
+
} | undefined;
|
|
355
|
+
report?: {
|
|
356
|
+
format?: "html" | "json" | "yaml" | "sarif" | "all" | null | undefined;
|
|
357
|
+
} | undefined;
|
|
358
|
+
auth?: {
|
|
359
|
+
strategy: "form";
|
|
360
|
+
loginUrl?: string | undefined;
|
|
361
|
+
userSelector?: string | null | undefined;
|
|
362
|
+
passSelector?: string | null | undefined;
|
|
363
|
+
} | {
|
|
364
|
+
strategy: "header";
|
|
365
|
+
headers: Record<string, string>;
|
|
366
|
+
} | null | undefined;
|
|
367
|
+
}>;
|
|
368
|
+
/** Parsed and validated project config */
|
|
369
|
+
type VulcnProjectConfig = z.infer<typeof VulcnProjectConfigSchema>;
|
|
370
|
+
/**
|
|
371
|
+
* Parse and validate a raw config object (from YAML.parse).
|
|
372
|
+
* All fields have defaults, so an empty object is valid.
|
|
373
|
+
*/
|
|
374
|
+
declare function parseProjectConfig(raw: unknown): VulcnProjectConfig;
|
|
375
|
+
/**
|
|
376
|
+
* Default config for `vulcn init`.
|
|
377
|
+
* Only includes fields that users are likely to customize.
|
|
378
|
+
*/
|
|
379
|
+
declare const DEFAULT_PROJECT_CONFIG: {
|
|
380
|
+
readonly target: "https://example.com";
|
|
381
|
+
readonly scan: {
|
|
382
|
+
readonly browser: "chromium";
|
|
383
|
+
readonly headless: true;
|
|
384
|
+
readonly timeout: 30000;
|
|
385
|
+
};
|
|
386
|
+
readonly payloads: {
|
|
387
|
+
readonly types: readonly ["xss"];
|
|
388
|
+
};
|
|
389
|
+
readonly detection: {
|
|
390
|
+
readonly xss: {
|
|
391
|
+
readonly dialogs: true;
|
|
392
|
+
readonly console: true;
|
|
393
|
+
readonly domMutation: false;
|
|
394
|
+
readonly severity: "high";
|
|
395
|
+
};
|
|
396
|
+
readonly reflection: {
|
|
397
|
+
readonly enabled: true;
|
|
398
|
+
};
|
|
399
|
+
readonly passive: true;
|
|
400
|
+
};
|
|
401
|
+
readonly crawl: {
|
|
402
|
+
readonly depth: 2;
|
|
403
|
+
readonly maxPages: 20;
|
|
404
|
+
readonly sameOrigin: true;
|
|
405
|
+
};
|
|
406
|
+
readonly report: {
|
|
407
|
+
readonly format: "html";
|
|
408
|
+
};
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Vulcn Project Discovery & Resolution
|
|
413
|
+
*
|
|
414
|
+
* Finds `.vulcn.yml` by walking up from `cwd`, parses the config,
|
|
415
|
+
* and resolves convention-based paths (sessions/, auth/, reports/).
|
|
416
|
+
*/
|
|
417
|
+
|
|
418
|
+
/** Config filename — presence marks a directory as a Vulcn project */
|
|
419
|
+
declare const CONFIG_FILENAME = ".vulcn.yml";
|
|
420
|
+
/** Convention-based subdirectory names */
|
|
421
|
+
declare const DIRS: {
|
|
422
|
+
readonly sessions: "sessions";
|
|
423
|
+
readonly auth: "auth";
|
|
424
|
+
readonly reports: "reports";
|
|
425
|
+
};
|
|
426
|
+
/** Resolved project paths */
|
|
427
|
+
interface ProjectPaths {
|
|
428
|
+
/** Absolute path to the project root (directory containing .vulcn.yml) */
|
|
429
|
+
root: string;
|
|
430
|
+
/** Absolute path to .vulcn.yml */
|
|
431
|
+
config: string;
|
|
432
|
+
/** Absolute path to sessions/ directory */
|
|
433
|
+
sessions: string;
|
|
434
|
+
/** Absolute path to auth/ directory */
|
|
435
|
+
auth: string;
|
|
436
|
+
/** Absolute path to reports/ directory */
|
|
437
|
+
reports: string;
|
|
438
|
+
}
|
|
439
|
+
/** Loaded project — config + paths */
|
|
440
|
+
interface VulcnProject {
|
|
441
|
+
/** Parsed and validated config */
|
|
442
|
+
config: VulcnProjectConfig;
|
|
443
|
+
/** Resolved absolute paths */
|
|
444
|
+
paths: ProjectPaths;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Find the project root by walking up from `startDir` looking for `.vulcn.yml`.
|
|
448
|
+
*
|
|
449
|
+
* @param startDir - Directory to start searching from (default: `cwd()`)
|
|
450
|
+
* @returns Absolute path to the project root, or `null` if not found
|
|
451
|
+
*/
|
|
452
|
+
declare function findProjectRoot(startDir?: string): string | null;
|
|
453
|
+
/**
|
|
454
|
+
* Resolve convention-based paths from a project root.
|
|
455
|
+
*/
|
|
456
|
+
declare function resolveProjectPaths(root: string): ProjectPaths;
|
|
457
|
+
/**
|
|
458
|
+
* Load a Vulcn project from a directory.
|
|
459
|
+
*
|
|
460
|
+
* Finds `.vulcn.yml`, parses it, validates with Zod, and resolves paths.
|
|
461
|
+
*
|
|
462
|
+
* @param startDir - Directory to start searching from (default: `cwd()`)
|
|
463
|
+
* @throws If `.vulcn.yml` is not found or invalid
|
|
464
|
+
*/
|
|
465
|
+
declare function loadProject(startDir?: string): Promise<VulcnProject>;
|
|
466
|
+
/**
|
|
467
|
+
* Load project config from a specific file path (no discovery).
|
|
468
|
+
* Useful for testing or when the path is already known.
|
|
469
|
+
*/
|
|
470
|
+
declare function loadProjectFromFile(configPath: string): Promise<VulcnProject>;
|
|
471
|
+
/**
|
|
472
|
+
* Ensure convention directories exist (sessions/, auth/, reports/).
|
|
473
|
+
* Called during init and before operations that write to these dirs.
|
|
474
|
+
*/
|
|
475
|
+
declare function ensureProjectDirs(paths: ProjectPaths, dirs?: Array<keyof typeof DIRS>): Promise<void>;
|
|
476
|
+
|
|
3
477
|
/**
|
|
4
478
|
* Payload Types for Vulcn
|
|
5
479
|
* Core types used by the engine and plugins
|
|
@@ -11,7 +485,7 @@ type PayloadCategory = "xss" | "sqli" | "ssrf" | "xxe" | "command-injection" | "
|
|
|
11
485
|
/**
|
|
12
486
|
* Payload source types
|
|
13
487
|
*/
|
|
14
|
-
type PayloadSource = "custom" | "payloadbox" | "plugin";
|
|
488
|
+
type PayloadSource = "curated" | "custom" | "payloadbox" | "plugin";
|
|
15
489
|
/**
|
|
16
490
|
* Runtime payload structure - used by plugins and the runner
|
|
17
491
|
*/
|
|
@@ -46,9 +520,18 @@ interface CustomPayloadFile {
|
|
|
46
520
|
version?: string;
|
|
47
521
|
payloads: CustomPayload[];
|
|
48
522
|
}
|
|
523
|
+
/**
|
|
524
|
+
* Determine finding severity based on vulnerability category.
|
|
525
|
+
*
|
|
526
|
+
* Central mapping used by all drivers and plugins — single source of truth
|
|
527
|
+
* so severity ratings remain consistent across Tier 1 (HTTP) and Tier 2 (browser) scans.
|
|
528
|
+
*/
|
|
529
|
+
declare function getSeverity(category: PayloadCategory): "critical" | "high" | "medium" | "low" | "info";
|
|
49
530
|
|
|
50
531
|
interface Finding {
|
|
51
532
|
type: PayloadCategory;
|
|
533
|
+
/** CWE identifier (e.g., "CWE-79" for XSS, "CWE-89" for SQLi) */
|
|
534
|
+
cwe?: string;
|
|
52
535
|
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
53
536
|
title: string;
|
|
54
537
|
description: string;
|
|
@@ -60,6 +543,111 @@ interface Finding {
|
|
|
60
543
|
metadata?: Record<string, unknown>;
|
|
61
544
|
}
|
|
62
545
|
|
|
546
|
+
/**
|
|
547
|
+
* Vulcn Error System
|
|
548
|
+
*
|
|
549
|
+
* Centralized error handling with severity classification.
|
|
550
|
+
* Components emit errors here instead of making local catch/swallow decisions.
|
|
551
|
+
*
|
|
552
|
+
* Severity levels:
|
|
553
|
+
* FATAL — Stop execution immediately. The operation cannot continue.
|
|
554
|
+
* Examples: report plugin fails to write, payload loading fails,
|
|
555
|
+
* driver can't launch browser.
|
|
556
|
+
*
|
|
557
|
+
* ERROR — Something broke but execution can continue. Record it.
|
|
558
|
+
* Examples: a single session times out, a plugin hook fails
|
|
559
|
+
* on a non-critical lifecycle event.
|
|
560
|
+
*
|
|
561
|
+
* WARN — Expected or recoverable. Log and move on.
|
|
562
|
+
* Examples: optional plugin not installed, browser page navigation
|
|
563
|
+
* intermittently fails, auth state not found.
|
|
564
|
+
*/
|
|
565
|
+
declare enum ErrorSeverity {
|
|
566
|
+
/** Stop execution — unrecoverable */
|
|
567
|
+
FATAL = "fatal",
|
|
568
|
+
/** Record and continue — something broke but others can proceed */
|
|
569
|
+
ERROR = "error",
|
|
570
|
+
/** Log and move on — expected or minor */
|
|
571
|
+
WARN = "warn"
|
|
572
|
+
}
|
|
573
|
+
declare class VulcnError extends Error {
|
|
574
|
+
readonly severity: ErrorSeverity;
|
|
575
|
+
readonly source: string;
|
|
576
|
+
readonly context?: Record<string, unknown>;
|
|
577
|
+
readonly timestamp: string;
|
|
578
|
+
constructor(message: string, options: {
|
|
579
|
+
severity: ErrorSeverity;
|
|
580
|
+
source: string;
|
|
581
|
+
cause?: unknown;
|
|
582
|
+
context?: Record<string, unknown>;
|
|
583
|
+
});
|
|
584
|
+
/**
|
|
585
|
+
* Wrap any caught error into a VulcnError.
|
|
586
|
+
* If it's already a VulcnError, returns it as-is.
|
|
587
|
+
*/
|
|
588
|
+
static from(err: unknown, defaults: {
|
|
589
|
+
severity: ErrorSeverity;
|
|
590
|
+
source: string;
|
|
591
|
+
context?: Record<string, unknown>;
|
|
592
|
+
}): VulcnError;
|
|
593
|
+
}
|
|
594
|
+
declare function fatal(message: string, source: string, options?: {
|
|
595
|
+
cause?: unknown;
|
|
596
|
+
context?: Record<string, unknown>;
|
|
597
|
+
}): VulcnError;
|
|
598
|
+
declare function error(message: string, source: string, options?: {
|
|
599
|
+
cause?: unknown;
|
|
600
|
+
context?: Record<string, unknown>;
|
|
601
|
+
}): VulcnError;
|
|
602
|
+
declare function warn(message: string, source: string, options?: {
|
|
603
|
+
cause?: unknown;
|
|
604
|
+
context?: Record<string, unknown>;
|
|
605
|
+
}): VulcnError;
|
|
606
|
+
type ErrorListener = (error: VulcnError) => void;
|
|
607
|
+
/**
|
|
608
|
+
* Central error handler for the Vulcn engine.
|
|
609
|
+
*
|
|
610
|
+
* - FATAL errors throw immediately (halt execution)
|
|
611
|
+
* - ERROR errors are recorded and logged
|
|
612
|
+
* - WARN errors are logged only
|
|
613
|
+
*
|
|
614
|
+
* At the end of a run/scan, call `getSummary()` to see everything that went wrong.
|
|
615
|
+
*/
|
|
616
|
+
declare class ErrorHandler {
|
|
617
|
+
private errors;
|
|
618
|
+
private listeners;
|
|
619
|
+
/**
|
|
620
|
+
* Handle an error based on its severity.
|
|
621
|
+
*
|
|
622
|
+
* - FATAL: logs, records, then THROWS (caller must not catch silently)
|
|
623
|
+
* - ERROR: logs and records
|
|
624
|
+
* - WARN: logs only
|
|
625
|
+
*/
|
|
626
|
+
handle(err: VulcnError): void;
|
|
627
|
+
/**
|
|
628
|
+
* Convenience: wrap a caught error and handle it.
|
|
629
|
+
*/
|
|
630
|
+
catch(err: unknown, defaults: {
|
|
631
|
+
severity: ErrorSeverity;
|
|
632
|
+
source: string;
|
|
633
|
+
context?: Record<string, unknown>;
|
|
634
|
+
}): void;
|
|
635
|
+
/** All recorded errors (FATAL + ERROR + WARN) */
|
|
636
|
+
getAll(): VulcnError[];
|
|
637
|
+
/** Only ERROR and FATAL */
|
|
638
|
+
getErrors(): VulcnError[];
|
|
639
|
+
/** Were there any errors (not just warnings)? */
|
|
640
|
+
hasErrors(): boolean;
|
|
641
|
+
/** Count by severity */
|
|
642
|
+
counts(): Record<ErrorSeverity, number>;
|
|
643
|
+
/** Human-readable summary for end-of-run reporting */
|
|
644
|
+
getSummary(): string;
|
|
645
|
+
/** Subscribe to errors as they happen */
|
|
646
|
+
onError(listener: ErrorListener): () => void;
|
|
647
|
+
/** Reset for a new run */
|
|
648
|
+
clear(): void;
|
|
649
|
+
}
|
|
650
|
+
|
|
63
651
|
/**
|
|
64
652
|
* Vulcn Plugin System Types
|
|
65
653
|
* @module @vulcn/engine/plugin
|
|
@@ -173,7 +761,7 @@ interface EngineInfo {
|
|
|
173
761
|
* Base context available to all plugin hooks
|
|
174
762
|
*/
|
|
175
763
|
interface PluginContext {
|
|
176
|
-
/** Plugin-specific
|
|
764
|
+
/** Plugin-specific configuration */
|
|
177
765
|
config: Record<string, unknown>;
|
|
178
766
|
/** Engine information */
|
|
179
767
|
engine: EngineInfo;
|
|
@@ -189,6 +777,13 @@ interface PluginContext {
|
|
|
189
777
|
addFinding: (finding: Finding) => void;
|
|
190
778
|
/** Scoped logger */
|
|
191
779
|
logger: PluginLogger;
|
|
780
|
+
/**
|
|
781
|
+
* Centralized error handler.
|
|
782
|
+
* Plugins MUST use this to surface errors instead of swallowing them:
|
|
783
|
+
* ctx.errors.fatal("can't write report", "plugin:report", { cause: err })
|
|
784
|
+
* ctx.errors.warn("optional feature unavailable", "plugin:passive")
|
|
785
|
+
*/
|
|
786
|
+
errors: ErrorHandler;
|
|
192
787
|
/** Fetch API for network requests */
|
|
193
788
|
fetch: typeof fetch;
|
|
194
789
|
}
|
|
@@ -234,31 +829,6 @@ interface DetectContext extends RunContext$1 {
|
|
|
234
829
|
/** Step ID for reporting */
|
|
235
830
|
stepId: string;
|
|
236
831
|
}
|
|
237
|
-
/**
|
|
238
|
-
* Plugin configuration in vulcn.config.yml
|
|
239
|
-
*/
|
|
240
|
-
interface PluginConfig {
|
|
241
|
-
/** Plugin name/path */
|
|
242
|
-
name: string;
|
|
243
|
-
/** Plugin-specific configuration */
|
|
244
|
-
config?: Record<string, unknown>;
|
|
245
|
-
/** Whether plugin is enabled (default: true) */
|
|
246
|
-
enabled?: boolean;
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Vulcn configuration file schema
|
|
250
|
-
*/
|
|
251
|
-
interface VulcnConfig {
|
|
252
|
-
/** Config version */
|
|
253
|
-
version: string;
|
|
254
|
-
/** Plugins to load */
|
|
255
|
-
plugins?: PluginConfig[];
|
|
256
|
-
/** Global settings */
|
|
257
|
-
settings?: {
|
|
258
|
-
headless?: boolean;
|
|
259
|
-
timeout?: number;
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
832
|
/**
|
|
263
833
|
* Loaded plugin instance with resolved config
|
|
264
834
|
*/
|
|
@@ -275,7 +845,11 @@ interface LoadedPlugin {
|
|
|
275
845
|
|
|
276
846
|
/**
|
|
277
847
|
* Vulcn Plugin Manager
|
|
278
|
-
* Handles plugin loading, lifecycle, and hook execution
|
|
848
|
+
* Handles plugin loading, lifecycle, and hook execution.
|
|
849
|
+
*
|
|
850
|
+
* The primary entry point is `loadFromConfig(config)` which takes
|
|
851
|
+
* a flat `VulcnProjectConfig` (from `.vulcn.yml`) and maps it to
|
|
852
|
+
* internal plugin configs automatically.
|
|
279
853
|
*/
|
|
280
854
|
|
|
281
855
|
/**
|
|
@@ -283,25 +857,16 @@ interface LoadedPlugin {
|
|
|
283
857
|
*/
|
|
284
858
|
declare class PluginManager {
|
|
285
859
|
private plugins;
|
|
286
|
-
private config;
|
|
287
860
|
private initialized;
|
|
861
|
+
private errorHandler;
|
|
288
862
|
/**
|
|
289
863
|
* Shared context passed to all plugins
|
|
290
864
|
*/
|
|
291
865
|
private sharedPayloads;
|
|
292
866
|
private sharedFindings;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
loadConfig(configPath?: string): Promise<VulcnConfig>;
|
|
297
|
-
/**
|
|
298
|
-
* Load all plugins from config
|
|
299
|
-
*/
|
|
300
|
-
loadPlugins(): Promise<void>;
|
|
301
|
-
/**
|
|
302
|
-
* Load a single plugin
|
|
303
|
-
*/
|
|
304
|
-
private loadPlugin;
|
|
867
|
+
constructor(errorHandler?: ErrorHandler);
|
|
868
|
+
/** Get the error handler for post-run inspection */
|
|
869
|
+
getErrorHandler(): ErrorHandler;
|
|
305
870
|
/**
|
|
306
871
|
* Validate plugin structure
|
|
307
872
|
*/
|
|
@@ -318,6 +883,15 @@ declare class PluginManager {
|
|
|
318
883
|
* Destroy all plugins (call onDestroy hooks)
|
|
319
884
|
*/
|
|
320
885
|
destroy(): Promise<void>;
|
|
886
|
+
/**
|
|
887
|
+
* Load the engine from a flat VulcnProjectConfig (from `.vulcn.yml`).
|
|
888
|
+
*
|
|
889
|
+
* This is the primary entry point for the new config system.
|
|
890
|
+
* Maps user-facing config keys to internal plugin configs automatically.
|
|
891
|
+
*
|
|
892
|
+
* @param config - Parsed and validated VulcnProjectConfig
|
|
893
|
+
*/
|
|
894
|
+
loadFromConfig(config: VulcnProjectConfig): Promise<void>;
|
|
321
895
|
/**
|
|
322
896
|
* Get all loaded payloads
|
|
323
897
|
*/
|
|
@@ -349,11 +923,14 @@ declare class PluginManager {
|
|
|
349
923
|
/**
|
|
350
924
|
* Create base context for plugins
|
|
351
925
|
*/
|
|
352
|
-
createContext(pluginConfig: Record<string, unknown
|
|
926
|
+
createContext(pluginConfig: Record<string, unknown>, pluginName?: string): PluginContext;
|
|
353
927
|
/**
|
|
354
928
|
* Create scoped logger for a plugin
|
|
355
929
|
*/
|
|
356
930
|
private createLogger;
|
|
931
|
+
private static readonly FATAL_HOOKS;
|
|
932
|
+
private static readonly ERROR_HOOKS;
|
|
933
|
+
private hookSeverity;
|
|
357
934
|
/**
|
|
358
935
|
* Call a hook on all plugins sequentially
|
|
359
936
|
*/
|
|
@@ -435,6 +1012,13 @@ interface RunContext {
|
|
|
435
1012
|
addFinding(finding: Finding): void;
|
|
436
1013
|
/** Logger */
|
|
437
1014
|
logger: DriverLogger;
|
|
1015
|
+
/**
|
|
1016
|
+
* Centralized error handler.
|
|
1017
|
+
* Drivers MUST use this to surface errors:
|
|
1018
|
+
* ctx.errors.fatal("session data malformed", "driver:browser")
|
|
1019
|
+
* ctx.errors.warn("page timeout", "driver:browser")
|
|
1020
|
+
*/
|
|
1021
|
+
errors: ErrorHandler;
|
|
438
1022
|
/** Running options */
|
|
439
1023
|
options: RunOptions;
|
|
440
1024
|
}
|
|
@@ -480,6 +1064,16 @@ interface RunOptions {
|
|
|
480
1064
|
onFinding?: (finding: Finding) => void;
|
|
481
1065
|
/** Callback for step completion */
|
|
482
1066
|
onStepComplete?: (stepId: string, payloadCount: number) => void;
|
|
1067
|
+
/**
|
|
1068
|
+
* Called by executeScan before each session starts.
|
|
1069
|
+
* Provides the session name, index, and total count for progress tracking.
|
|
1070
|
+
*/
|
|
1071
|
+
onSessionStart?: (session: Session, index: number, total: number) => void;
|
|
1072
|
+
/**
|
|
1073
|
+
* Called by executeScan after each session completes.
|
|
1074
|
+
* Provides the result for that session.
|
|
1075
|
+
*/
|
|
1076
|
+
onSessionEnd?: (session: Session, result: RunResult, index: number, total: number) => void;
|
|
483
1077
|
/**
|
|
484
1078
|
* Called by the driver runner after the page/environment is ready.
|
|
485
1079
|
* The driver-manager uses this to fire plugin onRunStart hooks
|
|
@@ -492,7 +1086,19 @@ interface RunOptions {
|
|
|
492
1086
|
* so plugins can flush pending async work.
|
|
493
1087
|
*/
|
|
494
1088
|
onBeforeClose?: (page: unknown) => Promise<void>;
|
|
495
|
-
/**
|
|
1089
|
+
/**
|
|
1090
|
+
* Per-session timeout in milliseconds.
|
|
1091
|
+
* If a session exceeds this duration, it will be aborted with a timeout error.
|
|
1092
|
+
* Both CLI and Worker benefit from this when using `executeScan`.
|
|
1093
|
+
*/
|
|
1094
|
+
timeout?: number;
|
|
1095
|
+
/** Shared browser instance (passed by executeScan for persistent mode) */
|
|
1096
|
+
browser?: unknown;
|
|
1097
|
+
/** JSON-stringified browser storage state (cookies, localStorage) for authenticated scans */
|
|
1098
|
+
storageState?: string;
|
|
1099
|
+
/** Extra HTTP headers to inject into every request (for header-based auth) */
|
|
1100
|
+
extraHeaders?: Record<string, string>;
|
|
1101
|
+
/** Allow additional driver-specific options */
|
|
496
1102
|
[key: string]: unknown;
|
|
497
1103
|
}
|
|
498
1104
|
/**
|
|
@@ -580,6 +1186,14 @@ interface VulcnDriver {
|
|
|
580
1186
|
recorder: RecorderDriver;
|
|
581
1187
|
/** Runner implementation */
|
|
582
1188
|
runner: RunnerDriver;
|
|
1189
|
+
/**
|
|
1190
|
+
* Create a shared resource (e.g., a browser instance) that can be
|
|
1191
|
+
* passed to execute() via ctx.options.
|
|
1192
|
+
*
|
|
1193
|
+
* Used by executeScan() to improve performance by reusing resources
|
|
1194
|
+
* across multiple sessions.
|
|
1195
|
+
*/
|
|
1196
|
+
createSharedResource?: (config: Record<string, unknown>, options: RunOptions) => Promise<unknown>;
|
|
583
1197
|
}
|
|
584
1198
|
/**
|
|
585
1199
|
* Driver source for loading
|
|
@@ -599,6 +1213,7 @@ interface LoadedDriver {
|
|
|
599
1213
|
* Handles driver loading, registration, and lifecycle.
|
|
600
1214
|
* Drivers are loaded from npm packages or local files.
|
|
601
1215
|
*/
|
|
1216
|
+
declare const ENGINE_VERSION: any;
|
|
602
1217
|
|
|
603
1218
|
/**
|
|
604
1219
|
* Driver Manager - loads and manages recording/running drivers
|
|
@@ -641,15 +1256,11 @@ declare class DriverManager {
|
|
|
641
1256
|
/**
|
|
642
1257
|
* Parse a YAML session string into a Session object.
|
|
643
1258
|
*
|
|
644
|
-
*
|
|
645
|
-
* Legacy sessions (those with non-namespaced step types like "click",
|
|
646
|
-
* "input", "navigate") are automatically converted to the driver format
|
|
647
|
-
* (e.g., "browser.click", "browser.input", "browser.navigate").
|
|
1259
|
+
* Sessions must use the driver format with a `driver` field.
|
|
648
1260
|
*
|
|
649
1261
|
* @param yaml - Raw YAML string
|
|
650
|
-
* @param defaultDriver - Driver to assign for legacy sessions (default: "browser")
|
|
651
1262
|
*/
|
|
652
|
-
parseSession(yaml: string
|
|
1263
|
+
parseSession(yaml: string): Session;
|
|
653
1264
|
/**
|
|
654
1265
|
* Start recording with a driver
|
|
655
1266
|
*/
|
|
@@ -796,57 +1407,10 @@ declare function decryptStorageState(encrypted: string, passphrase: string): str
|
|
|
796
1407
|
declare function getPassphrase(interactive?: string): string;
|
|
797
1408
|
|
|
798
1409
|
/**
|
|
799
|
-
* Vulcn Session
|
|
1410
|
+
* Vulcn Session Utilities
|
|
800
1411
|
*
|
|
801
|
-
*
|
|
802
|
-
*
|
|
803
|
-
* Structure:
|
|
804
|
-
* manifest.yml - scan config, session list, auth config
|
|
805
|
-
* auth/config.yml - login strategy, indicators
|
|
806
|
-
* auth/state.enc - encrypted storageState (cookies/localStorage)
|
|
807
|
-
* sessions/*.yml - individual session files (one per form)
|
|
808
|
-
* requests/*.json - captured HTTP metadata (for Tier 1 fast scan)
|
|
1412
|
+
* Types and utilities used by the driver system for HTTP request metadata.
|
|
809
1413
|
*/
|
|
810
|
-
|
|
811
|
-
/** Manifest file schema (manifest.yml) */
|
|
812
|
-
interface ScanManifest {
|
|
813
|
-
/** Format version */
|
|
814
|
-
version: "2";
|
|
815
|
-
/** Human-readable scan name */
|
|
816
|
-
name: string;
|
|
817
|
-
/** Target URL */
|
|
818
|
-
target: string;
|
|
819
|
-
/** When the scan was recorded */
|
|
820
|
-
recordedAt: string;
|
|
821
|
-
/** Driver name */
|
|
822
|
-
driver: string;
|
|
823
|
-
/** Driver configuration */
|
|
824
|
-
driverConfig: Record<string, unknown>;
|
|
825
|
-
/** Auth configuration (optional) */
|
|
826
|
-
auth?: {
|
|
827
|
-
strategy: string;
|
|
828
|
-
configFile?: string;
|
|
829
|
-
stateFile?: string;
|
|
830
|
-
loggedInIndicator?: string;
|
|
831
|
-
loggedOutIndicator?: string;
|
|
832
|
-
reAuthOn?: Array<Record<string, unknown>>;
|
|
833
|
-
};
|
|
834
|
-
/** Session file references */
|
|
835
|
-
sessions: SessionRef[];
|
|
836
|
-
/** Scan configuration */
|
|
837
|
-
scan?: {
|
|
838
|
-
tier?: "auto" | "http-only" | "browser-only";
|
|
839
|
-
parallel?: number;
|
|
840
|
-
timeout?: number;
|
|
841
|
-
};
|
|
842
|
-
}
|
|
843
|
-
/** Reference to a session file within the manifest */
|
|
844
|
-
interface SessionRef {
|
|
845
|
-
/** Relative path to session file */
|
|
846
|
-
file: string;
|
|
847
|
-
/** Whether this session has injectable inputs */
|
|
848
|
-
injectable?: boolean;
|
|
849
|
-
}
|
|
850
1414
|
/** HTTP request metadata for Tier 1 fast scanning */
|
|
851
1415
|
interface CapturedRequest {
|
|
852
1416
|
/** Request method */
|
|
@@ -864,54 +1428,5 @@ interface CapturedRequest {
|
|
|
864
1428
|
/** Session name this request belongs to */
|
|
865
1429
|
sessionName: string;
|
|
866
1430
|
}
|
|
867
|
-
/**
|
|
868
|
-
* Load a v2 session directory into Session[] ready for execution.
|
|
869
|
-
*
|
|
870
|
-
* @param dirPath - Path to the .vulcn/ directory
|
|
871
|
-
* @returns Array of sessions with manifest metadata attached
|
|
872
|
-
*/
|
|
873
|
-
declare function loadSessionDir(dirPath: string): Promise<{
|
|
874
|
-
manifest: ScanManifest;
|
|
875
|
-
sessions: Session[];
|
|
876
|
-
authConfig?: AuthConfig;
|
|
877
|
-
}>;
|
|
878
|
-
/**
|
|
879
|
-
* Check if a path is a v2 session directory.
|
|
880
|
-
*/
|
|
881
|
-
declare function isSessionDir(path: string): boolean;
|
|
882
|
-
/**
|
|
883
|
-
* Check if a path looks like a v2 session directory (by extension).
|
|
884
|
-
*/
|
|
885
|
-
declare function looksLikeSessionDir(path: string): boolean;
|
|
886
|
-
/**
|
|
887
|
-
* Save sessions to a v2 session directory.
|
|
888
|
-
*
|
|
889
|
-
* Creates the directory structure:
|
|
890
|
-
* <dirPath>/
|
|
891
|
-
* ├── manifest.yml
|
|
892
|
-
* ├── sessions/
|
|
893
|
-
* │ ├── <session-name>.yml
|
|
894
|
-
* │ └── ...
|
|
895
|
-
* └── requests/ (if HTTP metadata provided)
|
|
896
|
-
* └── ...
|
|
897
|
-
*/
|
|
898
|
-
declare function saveSessionDir(dirPath: string, options: {
|
|
899
|
-
name: string;
|
|
900
|
-
target: string;
|
|
901
|
-
driver: string;
|
|
902
|
-
driverConfig: Record<string, unknown>;
|
|
903
|
-
sessions: Session[];
|
|
904
|
-
authConfig?: AuthConfig;
|
|
905
|
-
encryptedState?: string;
|
|
906
|
-
requests?: CapturedRequest[];
|
|
907
|
-
}): Promise<void>;
|
|
908
|
-
/**
|
|
909
|
-
* Read encrypted auth state from a session directory.
|
|
910
|
-
*/
|
|
911
|
-
declare function readAuthState(dirPath: string): Promise<string | null>;
|
|
912
|
-
/**
|
|
913
|
-
* Read captured HTTP requests from a session directory.
|
|
914
|
-
*/
|
|
915
|
-
declare function readCapturedRequests(dirPath: string): Promise<CapturedRequest[]>;
|
|
916
1431
|
|
|
917
|
-
export { type AuthConfig, type CapturedRequest, type CrawlOptions, type Credentials, type CustomPayload, type CustomPayloadFile, DRIVER_API_VERSION, type DetectContext, type DriverLogger, DriverManager, type DriverSource, type EngineInfo, type Finding, type FormCredentials, type HeaderCredentials, type LoadedDriver, type LoadedPlugin as LoadedPluginInfo, PLUGIN_API_VERSION, type PayloadCategory, type PayloadSource, type
|
|
1432
|
+
export { type AuthConfig, CONFIG_FILENAME, type CapturedRequest, type CrawlOptions, type Credentials, type CustomPayload, type CustomPayloadFile, DEFAULT_PROJECT_CONFIG, DIRS, DRIVER_API_VERSION, type DetectContext, type DriverLogger, DriverManager, type DriverSource, ENGINE_VERSION, type EngineInfo, ErrorHandler, type ErrorListener, ErrorSeverity, type Finding, type FormCredentials, type HeaderCredentials, type LoadedDriver, type LoadedPlugin as LoadedPluginInfo, PLUGIN_API_VERSION, type PayloadCategory, type PayloadSource, type PluginContext, type PluginHooks, type PluginLogger, PluginManager, type RunContext$1 as PluginRunContext, type PluginSource, type ProjectPaths, type RecordContext, type RecordOptions, type RecorderDriver, type RecordingHandle, type RunContext, type RunOptions, type RunResult, type RunnerDriver, type RuntimePayload, type ScanContext, type Session, type Step, type VulcnDriver, VulcnError, type VulcnPlugin, type VulcnProject, type VulcnProjectConfig, VulcnProjectConfigSchema, decrypt, decryptCredentials, decryptStorageState, driverManager, encrypt, encryptCredentials, encryptStorageState, ensureProjectDirs, error, fatal, findProjectRoot, getPassphrase, getSeverity, loadProject, loadProjectFromFile, parseProjectConfig, pluginManager, resolveProjectPaths, warn };
|