@vulcn/engine 0.1.0 → 0.3.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.
- package/CHANGELOG.md +63 -1
- package/LICENSE +662 -21
- package/README.md +41 -175
- package/dist/index.cjs +841 -240
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +658 -55
- package/dist/index.d.ts +658 -55
- package/dist/index.js +821 -232
- package/dist/index.js.map +1 -1
- package/package.json +33 -16
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,86 @@
|
|
|
1
|
-
import { Page, Browser } from 'playwright';
|
|
2
1
|
import { z } from 'zod';
|
|
2
|
+
import { Page, Dialog, ConsoleMessage, Request, Response, Browser } from 'playwright';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Payload Types for Vulcn
|
|
6
|
+
* Core types used by the engine and plugins
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Valid payload categories
|
|
10
|
+
*/
|
|
11
|
+
type PayloadCategory = "xss" | "sqli" | "ssrf" | "xxe" | "command-injection" | "path-traversal" | "open-redirect" | "reflection" | "custom";
|
|
12
|
+
/**
|
|
13
|
+
* Payload source types
|
|
14
|
+
*/
|
|
15
|
+
type PayloadSource = "builtin" | "custom" | "payloadbox" | "plugin";
|
|
16
|
+
/**
|
|
17
|
+
* Runtime payload structure - used by plugins and the runner
|
|
18
|
+
*/
|
|
19
|
+
interface RuntimePayload {
|
|
20
|
+
/** Unique payload name */
|
|
21
|
+
name: string;
|
|
22
|
+
/** Vulnerability category */
|
|
23
|
+
category: PayloadCategory;
|
|
24
|
+
/** Human-readable description */
|
|
25
|
+
description: string;
|
|
26
|
+
/** Array of payload strings to inject */
|
|
27
|
+
payloads: string[];
|
|
28
|
+
/** Patterns to detect vulnerability (as RegExp) */
|
|
29
|
+
detectPatterns: RegExp[];
|
|
30
|
+
/** Where this payload came from */
|
|
31
|
+
source: PayloadSource;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Custom payload schema for YAML/JSON files (used by loader plugins)
|
|
35
|
+
*/
|
|
36
|
+
interface CustomPayload {
|
|
37
|
+
name: string;
|
|
38
|
+
category: PayloadCategory;
|
|
39
|
+
description?: string;
|
|
40
|
+
payloads: string[];
|
|
41
|
+
detectPatterns?: string[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Custom payload file schema
|
|
45
|
+
*/
|
|
46
|
+
interface CustomPayloadFile {
|
|
47
|
+
version?: string;
|
|
48
|
+
payloads: CustomPayload[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
type BrowserType = "chromium" | "firefox" | "webkit";
|
|
52
|
+
interface RecorderOptions {
|
|
53
|
+
browser?: BrowserType;
|
|
54
|
+
viewport?: {
|
|
55
|
+
width: number;
|
|
56
|
+
height: number;
|
|
57
|
+
};
|
|
58
|
+
headless?: boolean;
|
|
59
|
+
}
|
|
60
|
+
interface RunnerOptions {
|
|
61
|
+
browser?: BrowserType;
|
|
62
|
+
headless?: boolean;
|
|
63
|
+
onFinding?: (finding: Finding) => void;
|
|
64
|
+
}
|
|
65
|
+
interface Finding {
|
|
66
|
+
type: PayloadCategory;
|
|
67
|
+
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
68
|
+
title: string;
|
|
69
|
+
description: string;
|
|
70
|
+
stepId: string;
|
|
71
|
+
payload: string;
|
|
72
|
+
url: string;
|
|
73
|
+
evidence?: string;
|
|
74
|
+
/** Plugin-specific metadata */
|
|
75
|
+
metadata?: Record<string, unknown>;
|
|
76
|
+
}
|
|
77
|
+
interface RunResult$1 {
|
|
78
|
+
findings: Finding[];
|
|
79
|
+
stepsExecuted: number;
|
|
80
|
+
payloadsTested: number;
|
|
81
|
+
duration: number;
|
|
82
|
+
errors: string[];
|
|
83
|
+
}
|
|
3
84
|
|
|
4
85
|
declare const StepSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
5
86
|
id: z.ZodString;
|
|
@@ -137,7 +218,7 @@ declare const StepSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
|
137
218
|
timestamp: number;
|
|
138
219
|
duration: number;
|
|
139
220
|
}>]>;
|
|
140
|
-
type Step = z.infer<typeof StepSchema>;
|
|
221
|
+
type Step$1 = z.infer<typeof StepSchema>;
|
|
141
222
|
declare const SessionSchema: z.ZodObject<{
|
|
142
223
|
version: z.ZodDefault<z.ZodString>;
|
|
143
224
|
name: z.ZodString;
|
|
@@ -395,7 +476,7 @@ declare const SessionSchema: z.ZodObject<{
|
|
|
395
476
|
version?: string | undefined;
|
|
396
477
|
browser?: "chromium" | "firefox" | "webkit" | undefined;
|
|
397
478
|
}>;
|
|
398
|
-
type Session = z.infer<typeof SessionSchema>;
|
|
479
|
+
type Session$1 = z.infer<typeof SessionSchema>;
|
|
399
480
|
/**
|
|
400
481
|
* Create a new session object
|
|
401
482
|
*/
|
|
@@ -407,108 +488,630 @@ declare function createSession(options: {
|
|
|
407
488
|
width: number;
|
|
408
489
|
height: number;
|
|
409
490
|
};
|
|
410
|
-
}): Session;
|
|
491
|
+
}): Session$1;
|
|
411
492
|
/**
|
|
412
493
|
* Parse a session from YAML string
|
|
413
494
|
*/
|
|
414
|
-
declare function parseSession(yaml: string): Session;
|
|
495
|
+
declare function parseSession(yaml: string): Session$1;
|
|
415
496
|
/**
|
|
416
497
|
* Serialize a session to YAML string
|
|
417
498
|
*/
|
|
418
|
-
declare function serializeSession(session: Session): string;
|
|
499
|
+
declare function serializeSession(session: Session$1): string;
|
|
419
500
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
501
|
+
/**
|
|
502
|
+
* Vulcn Plugin System Types
|
|
503
|
+
* @module @vulcn/engine/plugin
|
|
504
|
+
*/
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Plugin API version - plugins declare compatibility
|
|
508
|
+
*/
|
|
509
|
+
declare const PLUGIN_API_VERSION = 1;
|
|
510
|
+
/**
|
|
511
|
+
* Plugin source types for identification
|
|
512
|
+
*/
|
|
513
|
+
type PluginSource = "builtin" | "npm" | "local" | "custom";
|
|
514
|
+
/**
|
|
515
|
+
* Main plugin interface
|
|
516
|
+
*/
|
|
517
|
+
interface VulcnPlugin {
|
|
518
|
+
/** Unique plugin name (e.g., "@vulcn/plugin-payloads") */
|
|
519
|
+
name: string;
|
|
520
|
+
/** Plugin version (semver) */
|
|
521
|
+
version: string;
|
|
522
|
+
/** Plugin API version this plugin targets */
|
|
523
|
+
apiVersion?: number;
|
|
524
|
+
/** Human-readable description */
|
|
525
|
+
description?: string;
|
|
526
|
+
/** Lifecycle hooks */
|
|
527
|
+
hooks?: PluginHooks;
|
|
528
|
+
/**
|
|
529
|
+
* Payloads provided by this plugin (Loaders)
|
|
530
|
+
* Can be static array or async function for lazy loading
|
|
531
|
+
*/
|
|
532
|
+
payloads?: RuntimePayload[] | (() => Promise<RuntimePayload[]>);
|
|
533
|
+
/**
|
|
534
|
+
* Zod schema for plugin configuration validation
|
|
535
|
+
*/
|
|
536
|
+
configSchema?: z.ZodSchema;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Plugin lifecycle hooks
|
|
540
|
+
*/
|
|
541
|
+
interface PluginHooks {
|
|
542
|
+
/**
|
|
543
|
+
* Called when plugin is loaded, before any operation
|
|
544
|
+
* Use for setup, loading payloads, etc.
|
|
545
|
+
*/
|
|
546
|
+
onInit?: (ctx: PluginContext) => Promise<void>;
|
|
547
|
+
/**
|
|
548
|
+
* Called when plugin is unloaded/cleanup
|
|
549
|
+
*/
|
|
550
|
+
onDestroy?: (ctx: PluginContext) => Promise<void>;
|
|
551
|
+
/** Called when recording starts */
|
|
552
|
+
onRecordStart?: (ctx: RecordContext) => Promise<void>;
|
|
553
|
+
/** Called for each recorded step, can transform */
|
|
554
|
+
onRecordStep?: (step: Step$1, ctx: RecordContext) => Promise<Step$1>;
|
|
555
|
+
/** Called when recording ends, can transform session */
|
|
556
|
+
onRecordEnd?: (session: Session$1, ctx: RecordContext) => Promise<Session$1>;
|
|
557
|
+
/** Called when run starts */
|
|
558
|
+
onRunStart?: (ctx: RunContext$1) => Promise<void>;
|
|
559
|
+
/** Called before each payload is injected, can transform payload */
|
|
560
|
+
onBeforePayload?: (payload: string, step: Step$1, ctx: RunContext$1) => Promise<string>;
|
|
561
|
+
/** Called after payload injection, for detection */
|
|
562
|
+
onAfterPayload?: (ctx: DetectContext) => Promise<Finding[]>;
|
|
563
|
+
/** Called when run ends, can transform results */
|
|
564
|
+
onRunEnd?: (result: RunResult$1, ctx: RunContext$1) => Promise<RunResult$1>;
|
|
565
|
+
/** Called on page load/navigation */
|
|
566
|
+
onPageLoad?: (page: Page, ctx: DetectContext) => Promise<Finding[]>;
|
|
567
|
+
/** Called when JavaScript alert/confirm/prompt appears */
|
|
568
|
+
onDialog?: (dialog: Dialog, ctx: DetectContext) => Promise<Finding | null>;
|
|
569
|
+
/** Called on console.log/warn/error */
|
|
570
|
+
onConsoleMessage?: (msg: ConsoleMessage, ctx: DetectContext) => Promise<Finding | null>;
|
|
571
|
+
/** Called on network request */
|
|
572
|
+
onNetworkRequest?: (request: Request, ctx: DetectContext) => Promise<Finding | null>;
|
|
573
|
+
/** Called on network response */
|
|
574
|
+
onNetworkResponse?: (response: Response, ctx: DetectContext) => Promise<Finding | null>;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Logger interface for plugins
|
|
578
|
+
*/
|
|
579
|
+
interface PluginLogger {
|
|
580
|
+
debug: (msg: string, ...args: unknown[]) => void;
|
|
581
|
+
info: (msg: string, ...args: unknown[]) => void;
|
|
582
|
+
warn: (msg: string, ...args: unknown[]) => void;
|
|
583
|
+
error: (msg: string, ...args: unknown[]) => void;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Engine information exposed to plugins
|
|
587
|
+
*/
|
|
588
|
+
interface EngineInfo {
|
|
589
|
+
version: string;
|
|
590
|
+
pluginApiVersion: number;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Base context available to all plugin hooks
|
|
594
|
+
*/
|
|
595
|
+
interface PluginContext {
|
|
596
|
+
/** Plugin-specific config from vulcn.config.yml */
|
|
597
|
+
config: Record<string, unknown>;
|
|
598
|
+
/** Engine information */
|
|
599
|
+
engine: EngineInfo;
|
|
600
|
+
/** Shared payload registry - loaders add payloads here */
|
|
601
|
+
payloads: RuntimePayload[];
|
|
602
|
+
/** Shared findings collection - detectors add findings here */
|
|
603
|
+
findings: Finding[];
|
|
604
|
+
/** Scoped logger */
|
|
605
|
+
logger: PluginLogger;
|
|
606
|
+
/** Fetch API for network requests */
|
|
607
|
+
fetch: typeof fetch;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Context for recording phase hooks
|
|
611
|
+
*/
|
|
612
|
+
interface RecordContext extends PluginContext {
|
|
613
|
+
/** Starting URL */
|
|
614
|
+
startUrl: string;
|
|
615
|
+
/** Browser type being used */
|
|
616
|
+
browser: BrowserType;
|
|
617
|
+
/** Playwright page instance */
|
|
618
|
+
page: Page;
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Context for running phase hooks
|
|
622
|
+
*/
|
|
623
|
+
interface RunContext$1 extends PluginContext {
|
|
624
|
+
/** Session being executed */
|
|
625
|
+
session: Session$1;
|
|
626
|
+
/** Playwright page instance */
|
|
627
|
+
page: Page;
|
|
628
|
+
/** Browser type being used */
|
|
629
|
+
browser: BrowserType;
|
|
630
|
+
/** Whether running headless */
|
|
631
|
+
headless: boolean;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Context for detection hooks
|
|
635
|
+
*/
|
|
636
|
+
interface DetectContext extends RunContext$1 {
|
|
637
|
+
/** Current step being tested */
|
|
638
|
+
step: Step$1;
|
|
639
|
+
/** Current payload set being tested */
|
|
640
|
+
payloadSet: RuntimePayload;
|
|
641
|
+
/** Actual payload value injected */
|
|
642
|
+
payloadValue: string;
|
|
643
|
+
/** Step ID for reporting */
|
|
644
|
+
stepId: string;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Plugin configuration in vulcn.config.yml
|
|
648
|
+
*/
|
|
649
|
+
interface PluginConfig {
|
|
650
|
+
/** Plugin name/path */
|
|
651
|
+
name: string;
|
|
652
|
+
/** Plugin-specific configuration */
|
|
653
|
+
config?: Record<string, unknown>;
|
|
654
|
+
/** Whether plugin is enabled (default: true) */
|
|
655
|
+
enabled?: boolean;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Vulcn configuration file schema
|
|
659
|
+
*/
|
|
660
|
+
interface VulcnConfig {
|
|
661
|
+
/** Config version */
|
|
662
|
+
version: string;
|
|
663
|
+
/** Plugins to load */
|
|
664
|
+
plugins?: PluginConfig[];
|
|
665
|
+
/** Global settings */
|
|
666
|
+
settings?: {
|
|
667
|
+
browser?: BrowserType;
|
|
668
|
+
headless?: boolean;
|
|
669
|
+
timeout?: number;
|
|
426
670
|
};
|
|
427
|
-
headless?: boolean;
|
|
428
671
|
}
|
|
429
|
-
|
|
430
|
-
|
|
672
|
+
/**
|
|
673
|
+
* Loaded plugin instance with resolved config
|
|
674
|
+
*/
|
|
675
|
+
interface LoadedPlugin {
|
|
676
|
+
/** Plugin definition */
|
|
677
|
+
plugin: VulcnPlugin;
|
|
678
|
+
/** Resolved configuration */
|
|
679
|
+
config: Record<string, unknown>;
|
|
680
|
+
/** Source of the plugin */
|
|
681
|
+
source: PluginSource;
|
|
682
|
+
/** Whether plugin is enabled */
|
|
683
|
+
enabled: boolean;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Vulcn Plugin Manager
|
|
688
|
+
* Handles plugin loading, lifecycle, and hook execution
|
|
689
|
+
*/
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Plugin Manager - loads, configures, and orchestrates plugins
|
|
693
|
+
*/
|
|
694
|
+
declare class PluginManager {
|
|
695
|
+
private plugins;
|
|
696
|
+
private config;
|
|
697
|
+
private initialized;
|
|
698
|
+
/**
|
|
699
|
+
* Shared context passed to all plugins
|
|
700
|
+
*/
|
|
701
|
+
private sharedPayloads;
|
|
702
|
+
private sharedFindings;
|
|
703
|
+
/**
|
|
704
|
+
* Load configuration from vulcn.config.yml
|
|
705
|
+
*/
|
|
706
|
+
loadConfig(configPath?: string): Promise<VulcnConfig>;
|
|
707
|
+
/**
|
|
708
|
+
* Load all plugins from config
|
|
709
|
+
*/
|
|
710
|
+
loadPlugins(): Promise<void>;
|
|
711
|
+
/**
|
|
712
|
+
* Load a single plugin
|
|
713
|
+
*/
|
|
714
|
+
private loadPlugin;
|
|
715
|
+
/**
|
|
716
|
+
* Validate plugin structure
|
|
717
|
+
*/
|
|
718
|
+
private validatePlugin;
|
|
719
|
+
/**
|
|
720
|
+
* Add a plugin programmatically (for testing or dynamic loading)
|
|
721
|
+
*/
|
|
722
|
+
addPlugin(plugin: VulcnPlugin, config?: Record<string, unknown>): void;
|
|
723
|
+
/**
|
|
724
|
+
* Initialize all plugins (call onInit hooks)
|
|
725
|
+
*/
|
|
726
|
+
initialize(): Promise<void>;
|
|
727
|
+
/**
|
|
728
|
+
* Destroy all plugins (call onDestroy hooks)
|
|
729
|
+
*/
|
|
730
|
+
destroy(): Promise<void>;
|
|
731
|
+
/**
|
|
732
|
+
* Get all loaded payloads
|
|
733
|
+
*/
|
|
734
|
+
getPayloads(): RuntimePayload[];
|
|
735
|
+
/**
|
|
736
|
+
* Get all collected findings
|
|
737
|
+
*/
|
|
738
|
+
getFindings(): Finding[];
|
|
739
|
+
/**
|
|
740
|
+
* Add a finding (used by detectors)
|
|
741
|
+
*/
|
|
742
|
+
addFinding(finding: Finding): void;
|
|
743
|
+
/**
|
|
744
|
+
* Add payloads (used by loaders)
|
|
745
|
+
*/
|
|
746
|
+
addPayloads(payloads: RuntimePayload[]): void;
|
|
747
|
+
/**
|
|
748
|
+
* Clear findings (for new run)
|
|
749
|
+
*/
|
|
750
|
+
clearFindings(): void;
|
|
751
|
+
/**
|
|
752
|
+
* Get loaded plugins
|
|
753
|
+
*/
|
|
754
|
+
getPlugins(): LoadedPlugin[];
|
|
755
|
+
/**
|
|
756
|
+
* Check if a plugin is loaded by name
|
|
757
|
+
*/
|
|
758
|
+
hasPlugin(name: string): boolean;
|
|
759
|
+
/**
|
|
760
|
+
* Create base context for plugins
|
|
761
|
+
*/
|
|
762
|
+
createContext(pluginConfig: Record<string, unknown>): PluginContext;
|
|
763
|
+
/**
|
|
764
|
+
* Create scoped logger for a plugin
|
|
765
|
+
*/
|
|
766
|
+
private createLogger;
|
|
767
|
+
/**
|
|
768
|
+
* Call a hook on all plugins sequentially
|
|
769
|
+
*/
|
|
770
|
+
callHook<K extends keyof PluginHooks>(hookName: K, executor: (hook: NonNullable<PluginHooks[K]>, ctx: PluginContext) => Promise<unknown>): Promise<void>;
|
|
771
|
+
/**
|
|
772
|
+
* Call a hook and collect results
|
|
773
|
+
*/
|
|
774
|
+
callHookCollect<K extends keyof PluginHooks, R>(hookName: K, executor: (hook: NonNullable<PluginHooks[K]>, ctx: PluginContext) => Promise<R | R[] | null>): Promise<R[]>;
|
|
775
|
+
/**
|
|
776
|
+
* Call a hook that transforms a value through the pipeline
|
|
777
|
+
*/
|
|
778
|
+
callHookPipe<T>(hookName: keyof PluginHooks, initial: T, executor: (hook: NonNullable<PluginHooks[typeof hookName]>, value: T, ctx: PluginContext) => Promise<T>): Promise<T>;
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Default shared plugin manager instance
|
|
782
|
+
*/
|
|
783
|
+
declare const pluginManager: PluginManager;
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Vulcn Driver System
|
|
787
|
+
*
|
|
788
|
+
* Drivers handle recording and running sessions for different targets:
|
|
789
|
+
* - browser: Web applications (Playwright)
|
|
790
|
+
* - api: REST/HTTP APIs
|
|
791
|
+
* - cli: Command-line tools
|
|
792
|
+
*
|
|
793
|
+
* Each driver implements RecorderDriver and RunnerDriver interfaces.
|
|
794
|
+
*/
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* Current driver API version
|
|
798
|
+
*/
|
|
799
|
+
declare const DRIVER_API_VERSION = 1;
|
|
800
|
+
/**
|
|
801
|
+
* Generic step - drivers define their own step types
|
|
802
|
+
*/
|
|
803
|
+
interface Step {
|
|
804
|
+
/** Unique step ID */
|
|
805
|
+
id: string;
|
|
806
|
+
/** Step type (namespaced, e.g., "browser.click", "api.request") */
|
|
807
|
+
type: string;
|
|
808
|
+
/** Timestamp when step was recorded */
|
|
809
|
+
timestamp: number;
|
|
810
|
+
/** Step-specific data */
|
|
811
|
+
[key: string]: unknown;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Generic session format
|
|
815
|
+
*/
|
|
816
|
+
interface Session {
|
|
817
|
+
/** Session name */
|
|
818
|
+
name: string;
|
|
819
|
+
/** Driver that recorded this session */
|
|
820
|
+
driver: string;
|
|
821
|
+
/** Driver-specific configuration */
|
|
822
|
+
driverConfig: Record<string, unknown>;
|
|
823
|
+
/** Recorded steps */
|
|
824
|
+
steps: Step[];
|
|
825
|
+
/** Session metadata */
|
|
826
|
+
metadata?: {
|
|
827
|
+
recordedAt?: string;
|
|
828
|
+
version?: string;
|
|
829
|
+
[key: string]: unknown;
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Running context passed to drivers
|
|
834
|
+
*/
|
|
835
|
+
interface RunContext {
|
|
836
|
+
/** Session being executed */
|
|
837
|
+
session: Session;
|
|
838
|
+
/** Plugin manager for calling hooks */
|
|
839
|
+
pluginManager: PluginManager;
|
|
840
|
+
/** Available payloads */
|
|
841
|
+
payloads: RuntimePayload[];
|
|
842
|
+
/** Collected findings */
|
|
843
|
+
findings: Finding[];
|
|
844
|
+
/** Add a finding */
|
|
845
|
+
addFinding(finding: Finding): void;
|
|
846
|
+
/** Logger */
|
|
847
|
+
logger: DriverLogger;
|
|
848
|
+
/** Running options */
|
|
849
|
+
options: RunOptions;
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Options for recording
|
|
853
|
+
*/
|
|
854
|
+
interface RecordOptions {
|
|
855
|
+
/** Driver-specific options */
|
|
856
|
+
[key: string]: unknown;
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Options for running
|
|
860
|
+
*/
|
|
861
|
+
interface RunOptions {
|
|
862
|
+
/** Run headless (for visual drivers) */
|
|
431
863
|
headless?: boolean;
|
|
864
|
+
/** Callback for findings */
|
|
432
865
|
onFinding?: (finding: Finding) => void;
|
|
866
|
+
/** Callback for step completion */
|
|
867
|
+
onStepComplete?: (stepId: string, payloadCount: number) => void;
|
|
868
|
+
/** Driver-specific options */
|
|
869
|
+
[key: string]: unknown;
|
|
433
870
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
title: string;
|
|
438
|
-
description: string;
|
|
439
|
-
stepId: string;
|
|
440
|
-
payload: string;
|
|
441
|
-
url: string;
|
|
442
|
-
evidence?: string;
|
|
443
|
-
}
|
|
871
|
+
/**
|
|
872
|
+
* Run result
|
|
873
|
+
*/
|
|
444
874
|
interface RunResult {
|
|
875
|
+
/** All findings */
|
|
445
876
|
findings: Finding[];
|
|
877
|
+
/** Steps executed */
|
|
446
878
|
stepsExecuted: number;
|
|
879
|
+
/** Payloads tested */
|
|
447
880
|
payloadsTested: number;
|
|
881
|
+
/** Duration in milliseconds */
|
|
448
882
|
duration: number;
|
|
883
|
+
/** Errors encountered */
|
|
449
884
|
errors: string[];
|
|
450
885
|
}
|
|
886
|
+
/**
|
|
887
|
+
* Driver logger
|
|
888
|
+
*/
|
|
889
|
+
interface DriverLogger {
|
|
890
|
+
debug(msg: string, ...args: unknown[]): void;
|
|
891
|
+
info(msg: string, ...args: unknown[]): void;
|
|
892
|
+
warn(msg: string, ...args: unknown[]): void;
|
|
893
|
+
error(msg: string, ...args: unknown[]): void;
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Recorder Driver Interface
|
|
897
|
+
*
|
|
898
|
+
* Implement this to add recording support for a target type.
|
|
899
|
+
*/
|
|
900
|
+
interface RecorderDriver {
|
|
901
|
+
/** Start recording and return control handle */
|
|
902
|
+
start(config: Record<string, unknown>, options: RecordOptions): Promise<RecordingHandle>;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Handle returned by RecorderDriver.start()
|
|
906
|
+
*/
|
|
907
|
+
interface RecordingHandle {
|
|
908
|
+
/** Stop recording and return the session */
|
|
909
|
+
stop(): Promise<Session>;
|
|
910
|
+
/** Abort recording without saving */
|
|
911
|
+
abort(): Promise<void>;
|
|
912
|
+
/** Get current steps (during recording) */
|
|
913
|
+
getSteps(): Step[];
|
|
914
|
+
/** Manually add a step */
|
|
915
|
+
addStep(step: Omit<Step, "id" | "timestamp">): void;
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Runner Driver Interface
|
|
919
|
+
*
|
|
920
|
+
* Implement this to add running/replay support for a target type.
|
|
921
|
+
*/
|
|
922
|
+
interface RunnerDriver {
|
|
923
|
+
/** Execute a session with payloads */
|
|
924
|
+
execute(session: Session, ctx: RunContext): Promise<RunResult>;
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Complete driver definition
|
|
928
|
+
*/
|
|
929
|
+
interface VulcnDriver {
|
|
930
|
+
/** Unique driver name (e.g., "browser", "api", "cli") */
|
|
931
|
+
name: string;
|
|
932
|
+
/** Driver version */
|
|
933
|
+
version: string;
|
|
934
|
+
/** Driver API version */
|
|
935
|
+
apiVersion?: number;
|
|
936
|
+
/** Human-readable description */
|
|
937
|
+
description?: string;
|
|
938
|
+
/** Configuration schema (Zod) */
|
|
939
|
+
configSchema?: z.ZodSchema;
|
|
940
|
+
/** Step types this driver handles */
|
|
941
|
+
stepTypes: string[];
|
|
942
|
+
/** Recorder implementation */
|
|
943
|
+
recorder: RecorderDriver;
|
|
944
|
+
/** Runner implementation */
|
|
945
|
+
runner: RunnerDriver;
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Driver source for loading
|
|
949
|
+
*/
|
|
950
|
+
type DriverSource = "npm" | "local" | "builtin";
|
|
951
|
+
/**
|
|
952
|
+
* Loaded driver with metadata
|
|
953
|
+
*/
|
|
954
|
+
interface LoadedDriver {
|
|
955
|
+
driver: VulcnDriver;
|
|
956
|
+
source: DriverSource;
|
|
957
|
+
}
|
|
451
958
|
|
|
959
|
+
/**
|
|
960
|
+
* Vulcn Driver Manager
|
|
961
|
+
*
|
|
962
|
+
* Handles driver loading, registration, and lifecycle.
|
|
963
|
+
* Drivers are loaded from npm packages or local files.
|
|
964
|
+
*/
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Driver Manager - loads and manages recording/running drivers
|
|
968
|
+
*/
|
|
969
|
+
declare class DriverManager {
|
|
970
|
+
private drivers;
|
|
971
|
+
private defaultDriver;
|
|
972
|
+
/**
|
|
973
|
+
* Register a driver
|
|
974
|
+
*/
|
|
975
|
+
register(driver: VulcnDriver, source?: DriverSource): void;
|
|
976
|
+
/**
|
|
977
|
+
* Load a driver from npm or local path
|
|
978
|
+
*/
|
|
979
|
+
load(nameOrPath: string): Promise<void>;
|
|
980
|
+
/**
|
|
981
|
+
* Get a loaded driver by name
|
|
982
|
+
*/
|
|
983
|
+
get(name: string): VulcnDriver | undefined;
|
|
984
|
+
/**
|
|
985
|
+
* Get the default driver
|
|
986
|
+
*/
|
|
987
|
+
getDefault(): VulcnDriver | undefined;
|
|
988
|
+
/**
|
|
989
|
+
* Set the default driver
|
|
990
|
+
*/
|
|
991
|
+
setDefault(name: string): void;
|
|
992
|
+
/**
|
|
993
|
+
* Check if a driver is registered
|
|
994
|
+
*/
|
|
995
|
+
has(name: string): boolean;
|
|
996
|
+
/**
|
|
997
|
+
* Get all registered drivers
|
|
998
|
+
*/
|
|
999
|
+
list(): LoadedDriver[];
|
|
1000
|
+
/**
|
|
1001
|
+
* Get driver for a session
|
|
1002
|
+
*/
|
|
1003
|
+
getForSession(session: Session): VulcnDriver;
|
|
1004
|
+
/**
|
|
1005
|
+
* Start recording with a driver
|
|
1006
|
+
*/
|
|
1007
|
+
startRecording(driverName: string, config: Record<string, unknown>, options?: RecordOptions): Promise<RecordingHandle>;
|
|
1008
|
+
/**
|
|
1009
|
+
* Execute a session
|
|
1010
|
+
*/
|
|
1011
|
+
execute(session: Session, pluginManager: PluginManager, options?: RunOptions): Promise<RunResult>;
|
|
1012
|
+
/**
|
|
1013
|
+
* Validate driver structure
|
|
1014
|
+
*/
|
|
1015
|
+
private validateDriver;
|
|
1016
|
+
/**
|
|
1017
|
+
* Create a scoped logger for a driver
|
|
1018
|
+
*/
|
|
1019
|
+
private createLogger;
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Default driver manager instance
|
|
1023
|
+
*/
|
|
1024
|
+
declare const driverManager: DriverManager;
|
|
1025
|
+
|
|
1026
|
+
/**
|
|
1027
|
+
* Recorder - captures browser interactions as a replayable session
|
|
1028
|
+
* v0.2.0: Plugin hooks for recording customization
|
|
1029
|
+
*/
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Configuration for the recorder
|
|
1033
|
+
*/
|
|
1034
|
+
interface RecorderConfig {
|
|
1035
|
+
/** Plugin manager to use (defaults to shared instance) */
|
|
1036
|
+
pluginManager?: PluginManager;
|
|
1037
|
+
}
|
|
452
1038
|
/**
|
|
453
1039
|
* Active recording session handle
|
|
454
1040
|
*/
|
|
455
1041
|
interface RecordingSession {
|
|
456
1042
|
/** Stop recording and return the session */
|
|
457
|
-
stop(): Promise<Session>;
|
|
1043
|
+
stop(): Promise<Session$1>;
|
|
458
1044
|
/** Get current recorded steps */
|
|
459
|
-
getSteps(): Step[];
|
|
1045
|
+
getSteps(): Step$1[];
|
|
460
1046
|
/** Get the Playwright page (for advanced use) */
|
|
461
1047
|
getPage(): Page;
|
|
462
1048
|
}
|
|
463
1049
|
/**
|
|
464
1050
|
* Recorder - captures browser interactions as a replayable session
|
|
1051
|
+
*
|
|
1052
|
+
* Uses plugin hooks for:
|
|
1053
|
+
* - onRecordStart: Called when recording starts
|
|
1054
|
+
* - onRecordStep: Called for each step, can transform
|
|
1055
|
+
* - onRecordEnd: Called when recording ends, can transform session
|
|
465
1056
|
*/
|
|
466
1057
|
declare class Recorder {
|
|
467
1058
|
/**
|
|
468
1059
|
* Start a new recording session
|
|
469
1060
|
* Opens a browser window for the user to interact with
|
|
470
1061
|
*/
|
|
471
|
-
static start(startUrl: string, options?: RecorderOptions): Promise<RecordingSession>;
|
|
1062
|
+
static start(startUrl: string, options?: RecorderOptions, config?: RecorderConfig): Promise<RecordingSession>;
|
|
1063
|
+
/**
|
|
1064
|
+
* Transform a step through plugin hooks
|
|
1065
|
+
* Returns null if the step should be filtered out
|
|
1066
|
+
*/
|
|
1067
|
+
private static transformStep;
|
|
472
1068
|
private static attachListeners;
|
|
473
1069
|
private static injectRecordingScript;
|
|
474
1070
|
}
|
|
475
1071
|
|
|
476
1072
|
/**
|
|
477
|
-
*
|
|
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
|
|
1073
|
+
* Runner - replays sessions with security payloads
|
|
1074
|
+
* v0.2.0: Plugin-based architecture for extensibility
|
|
499
1075
|
*/
|
|
500
|
-
declare function getPayloadsByCategory(category: PayloadCategory): Payload[];
|
|
501
1076
|
|
|
1077
|
+
interface RunnerConfig {
|
|
1078
|
+
/** Plugin manager to use (defaults to shared instance) */
|
|
1079
|
+
pluginManager?: PluginManager;
|
|
1080
|
+
}
|
|
502
1081
|
/**
|
|
503
1082
|
* Runner - replays sessions with security payloads
|
|
1083
|
+
*
|
|
1084
|
+
* Uses plugin hooks for:
|
|
1085
|
+
* - Payload loading (onInit)
|
|
1086
|
+
* - Payload transformation (onBeforePayload)
|
|
1087
|
+
* - Vulnerability detection (onAfterPayload, onDialog, onConsoleMessage, etc.)
|
|
1088
|
+
* - Results processing (onRunEnd)
|
|
504
1089
|
*/
|
|
505
1090
|
declare class Runner {
|
|
506
1091
|
/**
|
|
507
|
-
* Execute a session with security payloads
|
|
1092
|
+
* Execute a session with security payloads from plugins
|
|
1093
|
+
*
|
|
1094
|
+
* @param session - The recorded session to replay
|
|
1095
|
+
* @param options - Runner configuration
|
|
1096
|
+
* @param config - Plugin manager configuration
|
|
1097
|
+
*/
|
|
1098
|
+
static execute(session: Session$1, options?: RunnerOptions, config?: RunnerConfig): Promise<RunResult$1>;
|
|
1099
|
+
/**
|
|
1100
|
+
* Execute with explicit payloads (legacy API, for backwards compatibility)
|
|
1101
|
+
*/
|
|
1102
|
+
static executeWithPayloads(session: Session$1, payloads: RuntimePayload[], options?: RunnerOptions): Promise<RunResult$1>;
|
|
1103
|
+
/**
|
|
1104
|
+
* Replay session steps with payload injected at target step
|
|
508
1105
|
*/
|
|
509
|
-
static execute(session: Session, payloadNames: PayloadName[], options?: RunnerOptions): Promise<RunResult>;
|
|
510
1106
|
private static replayWithPayload;
|
|
511
|
-
|
|
1107
|
+
/**
|
|
1108
|
+
* Basic reflection check - fallback when no detection plugin is loaded
|
|
1109
|
+
*/
|
|
1110
|
+
private static checkReflection;
|
|
1111
|
+
/**
|
|
1112
|
+
* Determine severity based on vulnerability category
|
|
1113
|
+
*/
|
|
1114
|
+
private static getSeverity;
|
|
512
1115
|
}
|
|
513
1116
|
|
|
514
1117
|
interface LaunchOptions {
|
|
@@ -543,4 +1146,4 @@ declare function checkBrowsers(): Promise<{
|
|
|
543
1146
|
playwrightWebkit: boolean;
|
|
544
1147
|
}>;
|
|
545
1148
|
|
|
546
|
-
export {
|
|
1149
|
+
export { type BrowserLaunchResult, BrowserNotFoundError, type BrowserType, type CustomPayload, type CustomPayloadFile, DRIVER_API_VERSION, type DetectContext, type DriverLogger, DriverManager, type DriverSource, type EngineInfo, type Finding, type LaunchOptions, type Session$1 as LegacySession, type Step$1 as LegacyStep, type LoadedDriver, type LoadedPlugin as LoadedPluginInfo, PLUGIN_API_VERSION, type PayloadCategory, type PayloadSource, type PluginConfig, type PluginContext, type PluginHooks, type PluginLogger, PluginManager, type PluginSource, type RecordContext, type RecordOptions, Recorder, type RecorderDriver, type RecorderOptions, type RecordingHandle, type RecordingSession, type RunContext, type RunOptions, type RunResult, Runner, type RunnerDriver, type RunnerOptions, type RuntimePayload, type Session, SessionSchema, type Step, StepSchema, type VulcnConfig, type VulcnDriver, type VulcnPlugin, checkBrowsers, createSession, driverManager, installBrowsers, launchBrowser, parseSession, pluginManager, serializeSession };
|