kramscan 0.1.0 → 0.2.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 (105) hide show
  1. package/README.md +392 -87
  2. package/dist/agent/confirmation.d.ts +38 -0
  3. package/dist/agent/confirmation.js +210 -0
  4. package/dist/agent/context.d.ts +81 -0
  5. package/dist/agent/context.js +227 -0
  6. package/dist/agent/index.d.ts +10 -0
  7. package/dist/agent/index.js +32 -0
  8. package/dist/agent/orchestrator.d.ts +63 -0
  9. package/dist/agent/orchestrator.js +370 -0
  10. package/dist/agent/prompts/system.d.ts +6 -0
  11. package/dist/agent/prompts/system.js +116 -0
  12. package/dist/agent/skill-registry.d.ts +78 -0
  13. package/dist/agent/skill-registry.js +202 -0
  14. package/dist/agent/skills/analyze-findings.d.ts +22 -0
  15. package/dist/agent/skills/analyze-findings.js +191 -0
  16. package/dist/agent/skills/generate-report.d.ts +26 -0
  17. package/dist/agent/skills/generate-report.js +436 -0
  18. package/dist/agent/skills/health-check.d.ts +28 -0
  19. package/dist/agent/skills/health-check.js +344 -0
  20. package/dist/agent/skills/index.d.ts +9 -0
  21. package/dist/agent/skills/index.js +17 -0
  22. package/dist/agent/skills/verify-finding.d.ts +17 -0
  23. package/dist/agent/skills/verify-finding.js +91 -0
  24. package/dist/agent/skills/web-scan.d.ts +22 -0
  25. package/dist/agent/skills/web-scan.js +203 -0
  26. package/dist/agent/types.d.ts +141 -0
  27. package/dist/agent/types.js +16 -0
  28. package/dist/cli.d.ts +3 -0
  29. package/dist/cli.js +176 -139
  30. package/dist/commands/agent.d.ts +6 -0
  31. package/dist/commands/agent.js +250 -0
  32. package/dist/commands/ai.d.ts +2 -0
  33. package/dist/commands/ai.js +112 -0
  34. package/dist/commands/analyze.js +104 -55
  35. package/dist/commands/config.js +63 -37
  36. package/dist/commands/doctor.js +22 -17
  37. package/dist/commands/onboard.js +190 -125
  38. package/dist/commands/report.js +69 -77
  39. package/dist/commands/scan.js +261 -81
  40. package/dist/commands/scans.d.ts +2 -0
  41. package/dist/commands/scans.js +51 -0
  42. package/dist/core/ai-client.d.ts +7 -2
  43. package/dist/core/ai-client.js +231 -20
  44. package/dist/core/ai-payloads.d.ts +17 -0
  45. package/dist/core/ai-payloads.js +54 -0
  46. package/dist/core/config-schema.d.ts +197 -0
  47. package/dist/core/config-schema.js +68 -0
  48. package/dist/core/config-schema.test.d.ts +1 -0
  49. package/dist/core/config-schema.test.js +151 -0
  50. package/dist/core/config.d.ts +17 -36
  51. package/dist/core/config.js +261 -20
  52. package/dist/core/errors.d.ts +71 -0
  53. package/dist/core/errors.js +162 -0
  54. package/dist/core/scan-index.d.ts +19 -0
  55. package/dist/core/scan-index.js +52 -0
  56. package/dist/core/scan-storage.d.ts +11 -0
  57. package/dist/core/scan-storage.js +69 -0
  58. package/dist/core/scanner.d.ts +101 -4
  59. package/dist/core/scanner.js +432 -63
  60. package/dist/core/vulnerability-detector.d.ts +18 -2
  61. package/dist/core/vulnerability-detector.js +349 -38
  62. package/dist/core/vulnerability-detector.test.d.ts +1 -0
  63. package/dist/core/vulnerability-detector.test.js +210 -0
  64. package/dist/index.js +3 -0
  65. package/dist/plugins/PluginManager.d.ts +27 -0
  66. package/dist/plugins/PluginManager.js +166 -0
  67. package/dist/plugins/index.d.ts +7 -0
  68. package/dist/plugins/index.js +19 -0
  69. package/dist/plugins/types.d.ts +55 -0
  70. package/dist/plugins/types.js +25 -0
  71. package/dist/plugins/vulnerabilities/CSRFPlugin.d.ts +8 -0
  72. package/dist/plugins/vulnerabilities/CSRFPlugin.js +34 -0
  73. package/dist/plugins/vulnerabilities/SQLInjectionPlugin.d.ts +11 -0
  74. package/dist/plugins/vulnerabilities/SQLInjectionPlugin.js +109 -0
  75. package/dist/plugins/vulnerabilities/SecurityHeadersPlugin.d.ts +11 -0
  76. package/dist/plugins/vulnerabilities/SecurityHeadersPlugin.js +63 -0
  77. package/dist/plugins/vulnerabilities/SensitiveDataPlugin.d.ts +9 -0
  78. package/dist/plugins/vulnerabilities/SensitiveDataPlugin.js +32 -0
  79. package/dist/plugins/vulnerabilities/XSSPlugin.d.ts +15 -0
  80. package/dist/plugins/vulnerabilities/XSSPlugin.js +81 -0
  81. package/dist/reports/PdfGenerator.d.ts +36 -0
  82. package/dist/reports/PdfGenerator.js +379 -0
  83. package/dist/utils/logger.d.ts +33 -1
  84. package/dist/utils/logger.js +127 -8
  85. package/dist/utils/theme.d.ts +55 -0
  86. package/dist/utils/theme.js +195 -0
  87. package/package.json +27 -6
  88. package/dist/core/executor.d.ts +0 -2
  89. package/dist/core/executor.js +0 -74
  90. package/dist/core/logger.d.ts +0 -12
  91. package/dist/core/logger.js +0 -51
  92. package/dist/core/registry.d.ts +0 -3
  93. package/dist/core/registry.js +0 -35
  94. package/dist/core/storage.d.ts +0 -4
  95. package/dist/core/storage.js +0 -39
  96. package/dist/core/types.d.ts +0 -24
  97. package/dist/core/types.js +0 -2
  98. package/dist/skills/base.d.ts +0 -8
  99. package/dist/skills/base.js +0 -6
  100. package/dist/skills/builtin.d.ts +0 -4
  101. package/dist/skills/builtin.js +0 -71
  102. package/dist/skills/loader.d.ts +0 -2
  103. package/dist/skills/loader.js +0 -27
  104. package/dist/skills/types.d.ts +0 -46
  105. package/dist/skills/types.js +0 -2
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ /**
3
+ * Custom Error Types for KramScan
4
+ * Provides structured error handling with error codes
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ReportError = exports.AiError = exports.NetworkError = exports.ConfigError = exports.PluginError = exports.ScannerError = exports.KramScanError = exports.ErrorCode = void 0;
8
+ exports.isRetryable = isRetryable;
9
+ exports.shouldRetry = shouldRetry;
10
+ exports.getRetryDelay = getRetryDelay;
11
+ exports.setupGlobalErrorHandlers = setupGlobalErrorHandlers;
12
+ var ErrorCode;
13
+ (function (ErrorCode) {
14
+ // Scanner errors (SCN-xxx)
15
+ ErrorCode["SCN_INIT_FAILED"] = "SCN_INIT_FAILED";
16
+ ErrorCode["SCN_CRAWL_FAILED"] = "SCN_CRAWL_FAILED";
17
+ ErrorCode["SCN_TIMEOUT"] = "SCN_TIMEOUT";
18
+ ErrorCode["SCN_INVALID_URL"] = "SCN_INVALID_URL";
19
+ ErrorCode["SCN_SCOPE_VIOLATION"] = "SCN_SCOPE_VIOLATION";
20
+ ErrorCode["SCN_BROWSER_ERROR"] = "SCN_BROWSER_ERROR";
21
+ // Plugin errors (PLG-xxx)
22
+ ErrorCode["PLG_INIT_FAILED"] = "PLG_INIT_FAILED";
23
+ ErrorCode["PLG_EXECUTION_FAILED"] = "PLG_EXECUTION_FAILED";
24
+ ErrorCode["PLG_NOT_FOUND"] = "PLG_NOT_FOUND";
25
+ ErrorCode["PLG_DISABLED"] = "PLG_DISABLED";
26
+ ErrorCode["PLG_TIMEOUT"] = "PLG_TIMEOUT";
27
+ // Config errors (CFG-xxx)
28
+ ErrorCode["CFG_INVALID"] = "CFG_INVALID";
29
+ ErrorCode["CFG_NOT_FOUND"] = "CFG_NOT_FOUND";
30
+ ErrorCode["CFG_WRITE_FAILED"] = "CFG_WRITE_FAILED";
31
+ // Network errors (NET-xxx)
32
+ ErrorCode["NET_REQUEST_FAILED"] = "NET_REQUEST_FAILED";
33
+ ErrorCode["NET_RATE_LIMITED"] = "NET_RATE_LIMITED";
34
+ ErrorCode["NET_SSL_ERROR"] = "NET_SSL_ERROR";
35
+ // AI errors (AI-xxx)
36
+ ErrorCode["AI_INIT_FAILED"] = "AI_INIT_FAILED";
37
+ ErrorCode["AI_REQUEST_FAILED"] = "AI_REQUEST_FAILED";
38
+ ErrorCode["AI_QUOTA_EXCEEDED"] = "AI_QUOTA_EXCEEDED";
39
+ // Report errors (RPT-xxx)
40
+ ErrorCode["RPT_GENERATION_FAILED"] = "RPT_GENERATION_FAILED";
41
+ ErrorCode["RPT_INVALID_FORMAT"] = "RPT_INVALID_FORMAT";
42
+ })(ErrorCode || (exports.ErrorCode = ErrorCode = {}));
43
+ class KramScanError extends Error {
44
+ code;
45
+ statusCode;
46
+ retryable;
47
+ context;
48
+ timestamp;
49
+ constructor(message, options) {
50
+ super(message);
51
+ this.name = "KramScanError";
52
+ this.code = options.code;
53
+ this.statusCode = options.statusCode;
54
+ this.retryable = options.retryable ?? false;
55
+ this.context = options.context;
56
+ this.timestamp = new Date().toISOString();
57
+ // Maintains proper stack trace in V8 environments
58
+ if (Error.captureStackTrace) {
59
+ Error.captureStackTrace(this, KramScanError);
60
+ }
61
+ }
62
+ toJSON() {
63
+ return {
64
+ name: this.name,
65
+ message: this.message,
66
+ code: this.code,
67
+ statusCode: this.statusCode,
68
+ retryable: this.retryable,
69
+ context: this.context,
70
+ timestamp: this.timestamp,
71
+ stack: this.stack,
72
+ };
73
+ }
74
+ }
75
+ exports.KramScanError = KramScanError;
76
+ // Convenience error classes for common scenarios
77
+ class ScannerError extends KramScanError {
78
+ constructor(message, code = ErrorCode.SCN_CRAWL_FAILED, context) {
79
+ super(message, { code, retryable: true, context });
80
+ this.name = "ScannerError";
81
+ }
82
+ }
83
+ exports.ScannerError = ScannerError;
84
+ class PluginError extends KramScanError {
85
+ constructor(message, code = ErrorCode.PLG_EXECUTION_FAILED, context) {
86
+ super(message, { code, retryable: false, context });
87
+ this.name = "PluginError";
88
+ }
89
+ }
90
+ exports.PluginError = PluginError;
91
+ class ConfigError extends KramScanError {
92
+ constructor(message, code = ErrorCode.CFG_INVALID, context) {
93
+ super(message, { code, retryable: false, context });
94
+ this.name = "ConfigError";
95
+ }
96
+ }
97
+ exports.ConfigError = ConfigError;
98
+ class NetworkError extends KramScanError {
99
+ constructor(message, code = ErrorCode.NET_REQUEST_FAILED, context) {
100
+ super(message, { code, retryable: true, context });
101
+ this.name = "NetworkError";
102
+ }
103
+ }
104
+ exports.NetworkError = NetworkError;
105
+ class AiError extends KramScanError {
106
+ constructor(message, code = ErrorCode.AI_REQUEST_FAILED, context) {
107
+ super(message, { code, retryable: true, context });
108
+ this.name = "AiError";
109
+ }
110
+ }
111
+ exports.AiError = AiError;
112
+ class ReportError extends KramScanError {
113
+ constructor(message, code = ErrorCode.RPT_GENERATION_FAILED, context) {
114
+ super(message, { code, retryable: false, context });
115
+ this.name = "ReportError";
116
+ }
117
+ }
118
+ exports.ReportError = ReportError;
119
+ const defaultErrorHandlerConfig = {
120
+ maxRetries: 3,
121
+ baseDelay: 1000,
122
+ maxDelay: 10000,
123
+ retryableCodes: [
124
+ ErrorCode.SCN_CRAWL_FAILED,
125
+ ErrorCode.SCN_TIMEOUT,
126
+ ErrorCode.SCN_BROWSER_ERROR,
127
+ ErrorCode.NET_REQUEST_FAILED,
128
+ ErrorCode.PLG_EXECUTION_FAILED,
129
+ ErrorCode.AI_REQUEST_FAILED,
130
+ ],
131
+ };
132
+ function isRetryable(error, config = defaultErrorHandlerConfig) {
133
+ if (!error.retryable)
134
+ return false;
135
+ return config.retryableCodes.includes(error.code);
136
+ }
137
+ function shouldRetry(error, attempt, config = defaultErrorHandlerConfig) {
138
+ return attempt < config.maxRetries && isRetryable(error, config);
139
+ }
140
+ function getRetryDelay(error, attempt, config = defaultErrorHandlerConfig) {
141
+ const delay = Math.min(config.baseDelay * Math.pow(2, attempt), config.maxDelay);
142
+ // Add jitter to prevent thundering herd
143
+ const jitter = Math.random() * 0.3 * delay;
144
+ return Math.floor(delay + jitter);
145
+ }
146
+ // Global error handler for uncaught errors
147
+ function setupGlobalErrorHandlers() {
148
+ process.on("uncaughtException", (error) => {
149
+ console.error("[FATAL] Uncaught Exception:");
150
+ console.error(error.message);
151
+ if (error.stack) {
152
+ console.error(error.stack);
153
+ }
154
+ process.exit(1);
155
+ });
156
+ process.on("unhandledRejection", (reason, promise) => {
157
+ console.error("[FATAL] Unhandled Promise Rejection:");
158
+ console.error("Reason:", reason);
159
+ console.error("Promise:", promise);
160
+ process.exit(1);
161
+ });
162
+ }
@@ -0,0 +1,19 @@
1
+ export interface ScanIndexEntry {
2
+ id: string;
3
+ target: string;
4
+ hostname: string;
5
+ timestamp: string;
6
+ jsonPath: string;
7
+ pdfPath?: string;
8
+ summary: {
9
+ total: number;
10
+ critical: number;
11
+ high: number;
12
+ medium: number;
13
+ low: number;
14
+ info: number;
15
+ };
16
+ }
17
+ export declare function addScanToIndex(entry: Omit<ScanIndexEntry, "id">): Promise<ScanIndexEntry>;
18
+ export declare function listScans(limit?: number): Promise<ScanIndexEntry[]>;
19
+ export declare function getLatestScan(): Promise<ScanIndexEntry | null>;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.addScanToIndex = addScanToIndex;
7
+ exports.listScans = listScans;
8
+ exports.getLatestScan = getLatestScan;
9
+ const promises_1 = __importDefault(require("fs/promises"));
10
+ const os_1 = __importDefault(require("os"));
11
+ const path_1 = __importDefault(require("path"));
12
+ function getIndexPath() {
13
+ return path_1.default.join(os_1.default.homedir(), ".kramscan", "scans", "index.json");
14
+ }
15
+ async function readIndex() {
16
+ const indexPath = getIndexPath();
17
+ try {
18
+ const raw = await promises_1.default.readFile(indexPath, "utf-8");
19
+ const parsed = JSON.parse(raw);
20
+ if (Array.isArray(parsed)) {
21
+ return parsed;
22
+ }
23
+ return [];
24
+ }
25
+ catch {
26
+ return [];
27
+ }
28
+ }
29
+ async function writeIndex(entries) {
30
+ const indexPath = getIndexPath();
31
+ await promises_1.default.mkdir(path_1.default.dirname(indexPath), { recursive: true });
32
+ await promises_1.default.writeFile(indexPath, JSON.stringify(entries, null, 2), "utf-8");
33
+ }
34
+ async function addScanToIndex(entry) {
35
+ const hostname = entry.hostname || "unknown";
36
+ const id = `${new Date(entry.timestamp).getTime()}-${hostname}-${Math.random().toString(36).slice(2, 8)}`;
37
+ const full = { ...entry, id };
38
+ const existing = await readIndex();
39
+ const merged = [full, ...existing]
40
+ .filter((e, idx, arr) => arr.findIndex((x) => x.jsonPath === e.jsonPath) === idx)
41
+ .slice(0, 500);
42
+ await writeIndex(merged);
43
+ return full;
44
+ }
45
+ async function listScans(limit = 20) {
46
+ const entries = await readIndex();
47
+ return entries.slice(0, Math.max(1, limit));
48
+ }
49
+ async function getLatestScan() {
50
+ const entries = await readIndex();
51
+ return entries.length > 0 ? entries[0] : null;
52
+ }
@@ -0,0 +1,11 @@
1
+ export interface ResolvedScanFile {
2
+ filepath: string;
3
+ filename: string;
4
+ isLatest: boolean;
5
+ }
6
+ export declare function getKramScanHome(): string;
7
+ export declare function getScansDirectory(): string;
8
+ export declare function getReportsDirectory(): string;
9
+ export declare function ensureScansDirectory(): Promise<string>;
10
+ export declare function ensureReportsDirectory(): Promise<string>;
11
+ export declare function resolveScanFile(scanFile?: string): Promise<ResolvedScanFile>;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getKramScanHome = getKramScanHome;
7
+ exports.getScansDirectory = getScansDirectory;
8
+ exports.getReportsDirectory = getReportsDirectory;
9
+ exports.ensureScansDirectory = ensureScansDirectory;
10
+ exports.ensureReportsDirectory = ensureReportsDirectory;
11
+ exports.resolveScanFile = resolveScanFile;
12
+ const promises_1 = __importDefault(require("fs/promises"));
13
+ const os_1 = __importDefault(require("os"));
14
+ const path_1 = __importDefault(require("path"));
15
+ function getKramScanHome() {
16
+ return path_1.default.join(os_1.default.homedir(), ".kramscan");
17
+ }
18
+ function getScansDirectory() {
19
+ return path_1.default.join(getKramScanHome(), "scans");
20
+ }
21
+ function getReportsDirectory() {
22
+ return path_1.default.join(getKramScanHome(), "reports");
23
+ }
24
+ async function ensureScansDirectory() {
25
+ const scanDir = getScansDirectory();
26
+ await promises_1.default.mkdir(scanDir, { recursive: true });
27
+ return scanDir;
28
+ }
29
+ async function ensureReportsDirectory() {
30
+ const reportsDir = getReportsDirectory();
31
+ await promises_1.default.mkdir(reportsDir, { recursive: true });
32
+ return reportsDir;
33
+ }
34
+ async function resolveScanFile(scanFile) {
35
+ if (scanFile) {
36
+ const filepath = path_1.default.isAbsolute(scanFile)
37
+ ? scanFile
38
+ : path_1.default.join(process.cwd(), scanFile);
39
+ return {
40
+ filepath,
41
+ filename: path_1.default.basename(filepath),
42
+ isLatest: false,
43
+ };
44
+ }
45
+ const scanDir = await ensureScansDirectory();
46
+ const entries = await promises_1.default.readdir(scanDir, { withFileTypes: true });
47
+ const files = entries
48
+ .filter((entry) => entry.isFile() && entry.name.endsWith(".json"))
49
+ .map((entry) => entry.name);
50
+ if (files.length === 0) {
51
+ throw new Error("No scan results found. Run 'kramscan scan <url>' first.");
52
+ }
53
+ const filesWithStats = await Promise.all(files.map(async (filename) => {
54
+ const filepath = path_1.default.join(scanDir, filename);
55
+ const stats = await promises_1.default.stat(filepath);
56
+ return {
57
+ filename,
58
+ filepath,
59
+ mtimeMs: stats.mtimeMs,
60
+ };
61
+ }));
62
+ filesWithStats.sort((a, b) => b.mtimeMs - a.mtimeMs);
63
+ const latest = filesWithStats[0];
64
+ return {
65
+ filepath: latest.filepath,
66
+ filename: latest.filename,
67
+ isLatest: true,
68
+ };
69
+ }
@@ -1,21 +1,118 @@
1
- import { ScanResult } from "./vulnerability-detector";
1
+ import { EventEmitter } from "events";
2
+ import { ScanResult, Vulnerability } from "./vulnerability-detector";
3
+ export interface ScanEventMap {
4
+ "scan:start": {
5
+ target: string;
6
+ options: ScanOptions;
7
+ };
8
+ "scan:complete": {
9
+ result: ScanResult;
10
+ };
11
+ "scan:error": {
12
+ error: Error;
13
+ };
14
+ "crawl:start": {
15
+ url: string;
16
+ depth: number;
17
+ };
18
+ "crawl:page": {
19
+ url: string;
20
+ crawledCount: number;
21
+ maxPages: number;
22
+ };
23
+ "crawl:complete": {
24
+ url: string;
25
+ };
26
+ "crawl:error": {
27
+ url: string;
28
+ error: Error;
29
+ };
30
+ "form:test": {
31
+ url: string;
32
+ formCount: number;
33
+ };
34
+ "vuln:found": {
35
+ vulnerability: Vulnerability;
36
+ };
37
+ "plugin:execute": {
38
+ plugin: string;
39
+ url: string;
40
+ duration: number;
41
+ };
42
+ "progress": {
43
+ stage: string;
44
+ current: number;
45
+ total: number;
46
+ message?: string;
47
+ };
48
+ }
2
49
  export interface ScanOptions {
3
50
  depth?: number;
4
51
  timeout?: number;
5
52
  headless?: boolean;
53
+ maxPages?: number;
54
+ maxLinksPerPage?: number;
55
+ include?: string[];
56
+ exclude?: string[];
57
+ strictScope?: boolean;
58
+ profile?: string;
59
+ useAiPayloads?: boolean;
60
+ }
61
+ export interface ScanError {
62
+ url: string;
63
+ error: string;
64
+ plugin?: string;
6
65
  }
7
- export declare class Scanner {
66
+ export declare class Scanner extends EventEmitter {
8
67
  private browser;
9
68
  private detector;
10
69
  private visitedUrls;
11
70
  private crawledUrls;
12
71
  private testedForms;
13
72
  private requestsMade;
14
- constructor();
73
+ private headersChecked;
74
+ private rateLimiter;
75
+ private retryConfig;
76
+ private maxConcurrency;
77
+ private strictScope;
78
+ private baseOrigin;
79
+ private maxPages;
80
+ private maxLinksPerPage;
81
+ private includePatterns;
82
+ private excludePatterns;
83
+ private userAgent;
84
+ private scanErrors;
85
+ private pluginErrors;
86
+ private usePlugins;
87
+ private useAiPayloads;
88
+ private payloadGenerator;
89
+ constructor(usePlugins?: boolean);
90
+ private registerDefaultPlugins;
91
+ emit<K extends keyof ScanEventMap>(event: K, data: ScanEventMap[K]): boolean;
92
+ on<K extends keyof ScanEventMap>(event: K, listener: (data: ScanEventMap[K]) => void): this;
93
+ once<K extends keyof ScanEventMap>(event: K, listener: (data: ScanEventMap[K]) => void): this;
94
+ getScanErrors(): ScanError[];
95
+ getPluginErrors(): Map<string, Array<{
96
+ url: string;
97
+ error: string;
98
+ }>>;
99
+ private initializeScanSettings;
100
+ private resetScanState;
15
101
  initialize(options?: ScanOptions): Promise<void>;
16
102
  scan(targetUrl: string, options?: ScanOptions): Promise<ScanResult>;
103
+ private applyRateLimit;
104
+ private withRetry;
105
+ private createInstrumentedPage;
106
+ private runInIsolatedPage;
17
107
  private crawl;
18
- private testForms;
108
+ private runPlugins;
109
+ private processPluginResults;
110
+ private testUrlParametersWithPlugins;
111
+ private testFormsWithPlugins;
112
+ private runLegacyDetection;
113
+ private testFormsLegacy;
114
+ private testUrlParametersLegacy;
115
+ private runWithConcurrency;
19
116
  private testXSS;
20
117
  private testSQLi;
21
118
  private buildTestUrl;