@vulcn/engine 0.1.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.
@@ -0,0 +1,546 @@
1
+ import { Page, Browser } from 'playwright';
2
+ import { z } from 'zod';
3
+
4
+ declare const StepSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
5
+ id: z.ZodString;
6
+ type: z.ZodLiteral<"navigate">;
7
+ url: z.ZodString;
8
+ timestamp: z.ZodNumber;
9
+ }, "strip", z.ZodTypeAny, {
10
+ type: "navigate";
11
+ id: string;
12
+ url: string;
13
+ timestamp: number;
14
+ }, {
15
+ type: "navigate";
16
+ id: string;
17
+ url: string;
18
+ timestamp: number;
19
+ }>, z.ZodObject<{
20
+ id: z.ZodString;
21
+ type: z.ZodLiteral<"click">;
22
+ selector: z.ZodString;
23
+ position: z.ZodOptional<z.ZodObject<{
24
+ x: z.ZodNumber;
25
+ y: z.ZodNumber;
26
+ }, "strip", z.ZodTypeAny, {
27
+ x: number;
28
+ y: number;
29
+ }, {
30
+ x: number;
31
+ y: number;
32
+ }>>;
33
+ timestamp: z.ZodNumber;
34
+ }, "strip", z.ZodTypeAny, {
35
+ type: "click";
36
+ id: string;
37
+ timestamp: number;
38
+ selector: string;
39
+ position?: {
40
+ x: number;
41
+ y: number;
42
+ } | undefined;
43
+ }, {
44
+ type: "click";
45
+ id: string;
46
+ timestamp: number;
47
+ selector: string;
48
+ position?: {
49
+ x: number;
50
+ y: number;
51
+ } | undefined;
52
+ }>, z.ZodObject<{
53
+ id: z.ZodString;
54
+ type: z.ZodLiteral<"input">;
55
+ selector: z.ZodString;
56
+ value: z.ZodString;
57
+ injectable: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
58
+ timestamp: z.ZodNumber;
59
+ }, "strip", z.ZodTypeAny, {
60
+ type: "input";
61
+ value: string;
62
+ id: string;
63
+ timestamp: number;
64
+ selector: string;
65
+ injectable: boolean;
66
+ }, {
67
+ type: "input";
68
+ value: string;
69
+ id: string;
70
+ timestamp: number;
71
+ selector: string;
72
+ injectable?: boolean | undefined;
73
+ }>, z.ZodObject<{
74
+ id: z.ZodString;
75
+ type: z.ZodLiteral<"keypress">;
76
+ key: z.ZodString;
77
+ modifiers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
78
+ timestamp: z.ZodNumber;
79
+ }, "strip", z.ZodTypeAny, {
80
+ type: "keypress";
81
+ id: string;
82
+ timestamp: number;
83
+ key: string;
84
+ modifiers?: string[] | undefined;
85
+ }, {
86
+ type: "keypress";
87
+ id: string;
88
+ timestamp: number;
89
+ key: string;
90
+ modifiers?: string[] | undefined;
91
+ }>, z.ZodObject<{
92
+ id: z.ZodString;
93
+ type: z.ZodLiteral<"scroll">;
94
+ selector: z.ZodOptional<z.ZodString>;
95
+ position: z.ZodObject<{
96
+ x: z.ZodNumber;
97
+ y: z.ZodNumber;
98
+ }, "strip", z.ZodTypeAny, {
99
+ x: number;
100
+ y: number;
101
+ }, {
102
+ x: number;
103
+ y: number;
104
+ }>;
105
+ timestamp: z.ZodNumber;
106
+ }, "strip", z.ZodTypeAny, {
107
+ type: "scroll";
108
+ id: string;
109
+ timestamp: number;
110
+ position: {
111
+ x: number;
112
+ y: number;
113
+ };
114
+ selector?: string | undefined;
115
+ }, {
116
+ type: "scroll";
117
+ id: string;
118
+ timestamp: number;
119
+ position: {
120
+ x: number;
121
+ y: number;
122
+ };
123
+ selector?: string | undefined;
124
+ }>, z.ZodObject<{
125
+ id: z.ZodString;
126
+ type: z.ZodLiteral<"wait">;
127
+ duration: z.ZodNumber;
128
+ timestamp: z.ZodNumber;
129
+ }, "strip", z.ZodTypeAny, {
130
+ type: "wait";
131
+ id: string;
132
+ timestamp: number;
133
+ duration: number;
134
+ }, {
135
+ type: "wait";
136
+ id: string;
137
+ timestamp: number;
138
+ duration: number;
139
+ }>]>;
140
+ type Step = z.infer<typeof StepSchema>;
141
+ declare const SessionSchema: z.ZodObject<{
142
+ version: z.ZodDefault<z.ZodString>;
143
+ name: z.ZodString;
144
+ recordedAt: z.ZodString;
145
+ browser: z.ZodDefault<z.ZodEnum<["chromium", "firefox", "webkit"]>>;
146
+ viewport: z.ZodObject<{
147
+ width: z.ZodNumber;
148
+ height: z.ZodNumber;
149
+ }, "strip", z.ZodTypeAny, {
150
+ width: number;
151
+ height: number;
152
+ }, {
153
+ width: number;
154
+ height: number;
155
+ }>;
156
+ startUrl: z.ZodString;
157
+ steps: z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
158
+ id: z.ZodString;
159
+ type: z.ZodLiteral<"navigate">;
160
+ url: z.ZodString;
161
+ timestamp: z.ZodNumber;
162
+ }, "strip", z.ZodTypeAny, {
163
+ type: "navigate";
164
+ id: string;
165
+ url: string;
166
+ timestamp: number;
167
+ }, {
168
+ type: "navigate";
169
+ id: string;
170
+ url: string;
171
+ timestamp: number;
172
+ }>, z.ZodObject<{
173
+ id: z.ZodString;
174
+ type: z.ZodLiteral<"click">;
175
+ selector: z.ZodString;
176
+ position: z.ZodOptional<z.ZodObject<{
177
+ x: z.ZodNumber;
178
+ y: z.ZodNumber;
179
+ }, "strip", z.ZodTypeAny, {
180
+ x: number;
181
+ y: number;
182
+ }, {
183
+ x: number;
184
+ y: number;
185
+ }>>;
186
+ timestamp: z.ZodNumber;
187
+ }, "strip", z.ZodTypeAny, {
188
+ type: "click";
189
+ id: string;
190
+ timestamp: number;
191
+ selector: string;
192
+ position?: {
193
+ x: number;
194
+ y: number;
195
+ } | undefined;
196
+ }, {
197
+ type: "click";
198
+ id: string;
199
+ timestamp: number;
200
+ selector: string;
201
+ position?: {
202
+ x: number;
203
+ y: number;
204
+ } | undefined;
205
+ }>, z.ZodObject<{
206
+ id: z.ZodString;
207
+ type: z.ZodLiteral<"input">;
208
+ selector: z.ZodString;
209
+ value: z.ZodString;
210
+ injectable: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
211
+ timestamp: z.ZodNumber;
212
+ }, "strip", z.ZodTypeAny, {
213
+ type: "input";
214
+ value: string;
215
+ id: string;
216
+ timestamp: number;
217
+ selector: string;
218
+ injectable: boolean;
219
+ }, {
220
+ type: "input";
221
+ value: string;
222
+ id: string;
223
+ timestamp: number;
224
+ selector: string;
225
+ injectable?: boolean | undefined;
226
+ }>, z.ZodObject<{
227
+ id: z.ZodString;
228
+ type: z.ZodLiteral<"keypress">;
229
+ key: z.ZodString;
230
+ modifiers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
231
+ timestamp: z.ZodNumber;
232
+ }, "strip", z.ZodTypeAny, {
233
+ type: "keypress";
234
+ id: string;
235
+ timestamp: number;
236
+ key: string;
237
+ modifiers?: string[] | undefined;
238
+ }, {
239
+ type: "keypress";
240
+ id: string;
241
+ timestamp: number;
242
+ key: string;
243
+ modifiers?: string[] | undefined;
244
+ }>, z.ZodObject<{
245
+ id: z.ZodString;
246
+ type: z.ZodLiteral<"scroll">;
247
+ selector: z.ZodOptional<z.ZodString>;
248
+ position: z.ZodObject<{
249
+ x: z.ZodNumber;
250
+ y: z.ZodNumber;
251
+ }, "strip", z.ZodTypeAny, {
252
+ x: number;
253
+ y: number;
254
+ }, {
255
+ x: number;
256
+ y: number;
257
+ }>;
258
+ timestamp: z.ZodNumber;
259
+ }, "strip", z.ZodTypeAny, {
260
+ type: "scroll";
261
+ id: string;
262
+ timestamp: number;
263
+ position: {
264
+ x: number;
265
+ y: number;
266
+ };
267
+ selector?: string | undefined;
268
+ }, {
269
+ type: "scroll";
270
+ id: string;
271
+ timestamp: number;
272
+ position: {
273
+ x: number;
274
+ y: number;
275
+ };
276
+ selector?: string | undefined;
277
+ }>, z.ZodObject<{
278
+ id: z.ZodString;
279
+ type: z.ZodLiteral<"wait">;
280
+ duration: z.ZodNumber;
281
+ timestamp: z.ZodNumber;
282
+ }, "strip", z.ZodTypeAny, {
283
+ type: "wait";
284
+ id: string;
285
+ timestamp: number;
286
+ duration: number;
287
+ }, {
288
+ type: "wait";
289
+ id: string;
290
+ timestamp: number;
291
+ duration: number;
292
+ }>]>, "many">;
293
+ }, "strip", z.ZodTypeAny, {
294
+ version: string;
295
+ name: string;
296
+ recordedAt: string;
297
+ browser: "chromium" | "firefox" | "webkit";
298
+ viewport: {
299
+ width: number;
300
+ height: number;
301
+ };
302
+ startUrl: string;
303
+ steps: ({
304
+ type: "navigate";
305
+ id: string;
306
+ url: string;
307
+ timestamp: number;
308
+ } | {
309
+ type: "click";
310
+ id: string;
311
+ timestamp: number;
312
+ selector: string;
313
+ position?: {
314
+ x: number;
315
+ y: number;
316
+ } | undefined;
317
+ } | {
318
+ type: "input";
319
+ value: string;
320
+ id: string;
321
+ timestamp: number;
322
+ selector: string;
323
+ injectable: boolean;
324
+ } | {
325
+ type: "keypress";
326
+ id: string;
327
+ timestamp: number;
328
+ key: string;
329
+ modifiers?: string[] | undefined;
330
+ } | {
331
+ type: "scroll";
332
+ id: string;
333
+ timestamp: number;
334
+ position: {
335
+ x: number;
336
+ y: number;
337
+ };
338
+ selector?: string | undefined;
339
+ } | {
340
+ type: "wait";
341
+ id: string;
342
+ timestamp: number;
343
+ duration: number;
344
+ })[];
345
+ }, {
346
+ name: string;
347
+ recordedAt: string;
348
+ viewport: {
349
+ width: number;
350
+ height: number;
351
+ };
352
+ startUrl: string;
353
+ steps: ({
354
+ type: "navigate";
355
+ id: string;
356
+ url: string;
357
+ timestamp: number;
358
+ } | {
359
+ type: "click";
360
+ id: string;
361
+ timestamp: number;
362
+ selector: string;
363
+ position?: {
364
+ x: number;
365
+ y: number;
366
+ } | undefined;
367
+ } | {
368
+ type: "input";
369
+ value: string;
370
+ id: string;
371
+ timestamp: number;
372
+ selector: string;
373
+ injectable?: boolean | undefined;
374
+ } | {
375
+ type: "keypress";
376
+ id: string;
377
+ timestamp: number;
378
+ key: string;
379
+ modifiers?: string[] | undefined;
380
+ } | {
381
+ type: "scroll";
382
+ id: string;
383
+ timestamp: number;
384
+ position: {
385
+ x: number;
386
+ y: number;
387
+ };
388
+ selector?: string | undefined;
389
+ } | {
390
+ type: "wait";
391
+ id: string;
392
+ timestamp: number;
393
+ duration: number;
394
+ })[];
395
+ version?: string | undefined;
396
+ browser?: "chromium" | "firefox" | "webkit" | undefined;
397
+ }>;
398
+ type Session = z.infer<typeof SessionSchema>;
399
+ /**
400
+ * Create a new session object
401
+ */
402
+ declare function createSession(options: {
403
+ name: string;
404
+ startUrl: string;
405
+ browser?: "chromium" | "firefox" | "webkit";
406
+ viewport?: {
407
+ width: number;
408
+ height: number;
409
+ };
410
+ }): Session;
411
+ /**
412
+ * Parse a session from YAML string
413
+ */
414
+ declare function parseSession(yaml: string): Session;
415
+ /**
416
+ * Serialize a session to YAML string
417
+ */
418
+ declare function serializeSession(session: Session): string;
419
+
420
+ type BrowserType = "chromium" | "firefox" | "webkit";
421
+ interface RecorderOptions {
422
+ browser?: BrowserType;
423
+ viewport?: {
424
+ width: number;
425
+ height: number;
426
+ };
427
+ headless?: boolean;
428
+ }
429
+ interface RunnerOptions {
430
+ browser?: BrowserType;
431
+ headless?: boolean;
432
+ onFinding?: (finding: Finding) => void;
433
+ }
434
+ interface Finding {
435
+ type: "xss" | "sqli" | "ssrf" | "path-traversal" | "custom";
436
+ severity: "critical" | "high" | "medium" | "low" | "info";
437
+ title: string;
438
+ description: string;
439
+ stepId: string;
440
+ payload: string;
441
+ url: string;
442
+ evidence?: string;
443
+ }
444
+ interface RunResult {
445
+ findings: Finding[];
446
+ stepsExecuted: number;
447
+ payloadsTested: number;
448
+ duration: number;
449
+ errors: string[];
450
+ }
451
+
452
+ /**
453
+ * Active recording session handle
454
+ */
455
+ interface RecordingSession {
456
+ /** Stop recording and return the session */
457
+ stop(): Promise<Session>;
458
+ /** Get current recorded steps */
459
+ getSteps(): Step[];
460
+ /** Get the Playwright page (for advanced use) */
461
+ getPage(): Page;
462
+ }
463
+ /**
464
+ * Recorder - captures browser interactions as a replayable session
465
+ */
466
+ declare class Recorder {
467
+ /**
468
+ * Start a new recording session
469
+ * Opens a browser window for the user to interact with
470
+ */
471
+ static start(startUrl: string, options?: RecorderOptions): Promise<RecordingSession>;
472
+ private static attachListeners;
473
+ private static injectRecordingScript;
474
+ }
475
+
476
+ /**
477
+ * Built-in security payloads
478
+ */
479
+ type PayloadCategory = "xss" | "sqli" | "ssrf" | "path-traversal";
480
+ type PayloadName = "xss-basic" | "xss-event" | "xss-svg" | "sqli-basic" | "sqli-error" | "sqli-blind";
481
+ interface Payload {
482
+ name: PayloadName;
483
+ category: PayloadCategory;
484
+ payloads: string[];
485
+ detectPatterns: RegExp[];
486
+ description: string;
487
+ }
488
+ declare const BUILTIN_PAYLOADS: Record<PayloadName, Payload>;
489
+ /**
490
+ * Get payloads by name
491
+ */
492
+ declare function getPayload(name: PayloadName): Payload | undefined;
493
+ /**
494
+ * Get all payload names
495
+ */
496
+ declare function getPayloadNames(): PayloadName[];
497
+ /**
498
+ * Get payloads by category
499
+ */
500
+ declare function getPayloadsByCategory(category: PayloadCategory): Payload[];
501
+
502
+ /**
503
+ * Runner - replays sessions with security payloads
504
+ */
505
+ declare class Runner {
506
+ /**
507
+ * Execute a session with security payloads
508
+ */
509
+ static execute(session: Session, payloadNames: PayloadName[], options?: RunnerOptions): Promise<RunResult>;
510
+ private static replayWithPayload;
511
+ private static checkForVulnerability;
512
+ }
513
+
514
+ interface LaunchOptions {
515
+ browser?: BrowserType;
516
+ headless?: boolean;
517
+ }
518
+ interface BrowserLaunchResult {
519
+ browser: Browser;
520
+ channel?: string;
521
+ }
522
+ declare class BrowserNotFoundError extends Error {
523
+ constructor(message: string);
524
+ }
525
+ /**
526
+ * Launch a browser with smart fallback:
527
+ * 1. Try system Chrome/Edge first (zero-install experience)
528
+ * 2. Fall back to Playwright's bundled browsers
529
+ */
530
+ declare function launchBrowser(options?: LaunchOptions): Promise<BrowserLaunchResult>;
531
+ /**
532
+ * Install Playwright browsers
533
+ */
534
+ declare function installBrowsers(browsers?: BrowserType[]): Promise<void>;
535
+ /**
536
+ * Check which browsers are available
537
+ */
538
+ declare function checkBrowsers(): Promise<{
539
+ systemChrome: boolean;
540
+ systemEdge: boolean;
541
+ playwrightChromium: boolean;
542
+ playwrightFirefox: boolean;
543
+ playwrightWebkit: boolean;
544
+ }>;
545
+
546
+ export { BUILTIN_PAYLOADS, type BrowserLaunchResult, BrowserNotFoundError, type BrowserType, type Finding, type LaunchOptions, type Payload, type PayloadCategory, type PayloadName, Recorder, type RecorderOptions, type RecordingSession, type RunResult, Runner, type RunnerOptions, type Session, SessionSchema, type Step, StepSchema, checkBrowsers, createSession, getPayload, getPayloadNames, getPayloadsByCategory, installBrowsers, launchBrowser, parseSession, serializeSession };