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.
- package/README.md +392 -87
- package/dist/agent/confirmation.d.ts +38 -0
- package/dist/agent/confirmation.js +210 -0
- package/dist/agent/context.d.ts +81 -0
- package/dist/agent/context.js +227 -0
- package/dist/agent/index.d.ts +10 -0
- package/dist/agent/index.js +32 -0
- package/dist/agent/orchestrator.d.ts +63 -0
- package/dist/agent/orchestrator.js +370 -0
- package/dist/agent/prompts/system.d.ts +6 -0
- package/dist/agent/prompts/system.js +116 -0
- package/dist/agent/skill-registry.d.ts +78 -0
- package/dist/agent/skill-registry.js +202 -0
- package/dist/agent/skills/analyze-findings.d.ts +22 -0
- package/dist/agent/skills/analyze-findings.js +191 -0
- package/dist/agent/skills/generate-report.d.ts +26 -0
- package/dist/agent/skills/generate-report.js +436 -0
- package/dist/agent/skills/health-check.d.ts +28 -0
- package/dist/agent/skills/health-check.js +344 -0
- package/dist/agent/skills/index.d.ts +9 -0
- package/dist/agent/skills/index.js +17 -0
- package/dist/agent/skills/verify-finding.d.ts +17 -0
- package/dist/agent/skills/verify-finding.js +91 -0
- package/dist/agent/skills/web-scan.d.ts +22 -0
- package/dist/agent/skills/web-scan.js +203 -0
- package/dist/agent/types.d.ts +141 -0
- package/dist/agent/types.js +16 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +176 -139
- package/dist/commands/agent.d.ts +6 -0
- package/dist/commands/agent.js +250 -0
- package/dist/commands/ai.d.ts +2 -0
- package/dist/commands/ai.js +112 -0
- package/dist/commands/analyze.js +104 -55
- package/dist/commands/config.js +63 -37
- package/dist/commands/doctor.js +22 -17
- package/dist/commands/onboard.js +190 -125
- package/dist/commands/report.js +69 -77
- package/dist/commands/scan.js +261 -81
- package/dist/commands/scans.d.ts +2 -0
- package/dist/commands/scans.js +51 -0
- package/dist/core/ai-client.d.ts +7 -2
- package/dist/core/ai-client.js +231 -20
- package/dist/core/ai-payloads.d.ts +17 -0
- package/dist/core/ai-payloads.js +54 -0
- package/dist/core/config-schema.d.ts +197 -0
- package/dist/core/config-schema.js +68 -0
- package/dist/core/config-schema.test.d.ts +1 -0
- package/dist/core/config-schema.test.js +151 -0
- package/dist/core/config.d.ts +17 -36
- package/dist/core/config.js +261 -20
- package/dist/core/errors.d.ts +71 -0
- package/dist/core/errors.js +162 -0
- package/dist/core/scan-index.d.ts +19 -0
- package/dist/core/scan-index.js +52 -0
- package/dist/core/scan-storage.d.ts +11 -0
- package/dist/core/scan-storage.js +69 -0
- package/dist/core/scanner.d.ts +101 -4
- package/dist/core/scanner.js +432 -63
- package/dist/core/vulnerability-detector.d.ts +18 -2
- package/dist/core/vulnerability-detector.js +349 -38
- package/dist/core/vulnerability-detector.test.d.ts +1 -0
- package/dist/core/vulnerability-detector.test.js +210 -0
- package/dist/index.js +3 -0
- package/dist/plugins/PluginManager.d.ts +27 -0
- package/dist/plugins/PluginManager.js +166 -0
- package/dist/plugins/index.d.ts +7 -0
- package/dist/plugins/index.js +19 -0
- package/dist/plugins/types.d.ts +55 -0
- package/dist/plugins/types.js +25 -0
- package/dist/plugins/vulnerabilities/CSRFPlugin.d.ts +8 -0
- package/dist/plugins/vulnerabilities/CSRFPlugin.js +34 -0
- package/dist/plugins/vulnerabilities/SQLInjectionPlugin.d.ts +11 -0
- package/dist/plugins/vulnerabilities/SQLInjectionPlugin.js +109 -0
- package/dist/plugins/vulnerabilities/SecurityHeadersPlugin.d.ts +11 -0
- package/dist/plugins/vulnerabilities/SecurityHeadersPlugin.js +63 -0
- package/dist/plugins/vulnerabilities/SensitiveDataPlugin.d.ts +9 -0
- package/dist/plugins/vulnerabilities/SensitiveDataPlugin.js +32 -0
- package/dist/plugins/vulnerabilities/XSSPlugin.d.ts +15 -0
- package/dist/plugins/vulnerabilities/XSSPlugin.js +81 -0
- package/dist/reports/PdfGenerator.d.ts +36 -0
- package/dist/reports/PdfGenerator.js +379 -0
- package/dist/utils/logger.d.ts +33 -1
- package/dist/utils/logger.js +127 -8
- package/dist/utils/theme.d.ts +55 -0
- package/dist/utils/theme.js +195 -0
- package/package.json +27 -6
- package/dist/core/executor.d.ts +0 -2
- package/dist/core/executor.js +0 -74
- package/dist/core/logger.d.ts +0 -12
- package/dist/core/logger.js +0 -51
- package/dist/core/registry.d.ts +0 -3
- package/dist/core/registry.js +0 -35
- package/dist/core/storage.d.ts +0 -4
- package/dist/core/storage.js +0 -39
- package/dist/core/types.d.ts +0 -24
- package/dist/core/types.js +0 -2
- package/dist/skills/base.d.ts +0 -8
- package/dist/skills/base.js +0 -6
- package/dist/skills/builtin.d.ts +0 -4
- package/dist/skills/builtin.js +0 -71
- package/dist/skills/loader.d.ts +0 -2
- package/dist/skills/loader.js +0 -27
- package/dist/skills/types.d.ts +0 -46
- package/dist/skills/types.js +0 -2
package/dist/core/ai-client.js
CHANGED
|
@@ -4,9 +4,54 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createAIClient = createAIClient;
|
|
7
|
+
exports.generateExecutiveSummary = generateExecutiveSummary;
|
|
7
8
|
const openai_1 = __importDefault(require("openai"));
|
|
8
9
|
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
10
|
+
const generative_ai_1 = require("@google/generative-ai");
|
|
11
|
+
const mistralai_1 = require("@mistralai/mistralai");
|
|
9
12
|
const config_1 = require("./config");
|
|
13
|
+
function getApiKeyFromEnv(provider) {
|
|
14
|
+
const envVars = {
|
|
15
|
+
openai: process.env.OPENAI_API_KEY || "",
|
|
16
|
+
anthropic: process.env.ANTHROPIC_API_KEY || "",
|
|
17
|
+
gemini: process.env.GEMINI_API_KEY || "",
|
|
18
|
+
mistral: process.env.MISTRAL_API_KEY || "",
|
|
19
|
+
openrouter: process.env.OPENROUTER_API_KEY || "",
|
|
20
|
+
kimi: process.env.KIMI_API_KEY || "",
|
|
21
|
+
groq: process.env.GROQ_API_KEY || "",
|
|
22
|
+
};
|
|
23
|
+
return envVars[provider] || "";
|
|
24
|
+
}
|
|
25
|
+
async function createAIClient() {
|
|
26
|
+
const config = await (0, config_1.getConfig)();
|
|
27
|
+
if (!config.ai.enabled) {
|
|
28
|
+
throw new Error("AI analysis is not enabled. Run 'kramscan onboard' first.");
|
|
29
|
+
}
|
|
30
|
+
const provider = config.ai.provider;
|
|
31
|
+
const apiKey = config.ai.apiKey || getApiKeyFromEnv(provider);
|
|
32
|
+
const model = config.ai.defaultModel;
|
|
33
|
+
if (!apiKey) {
|
|
34
|
+
throw new Error(`No API key configured for ${provider}. Run 'kramscan onboard' or set ${provider.toUpperCase()}_API_KEY environment variable.`);
|
|
35
|
+
}
|
|
36
|
+
switch (provider) {
|
|
37
|
+
case "openai":
|
|
38
|
+
return new OpenAIClient(apiKey, model);
|
|
39
|
+
case "anthropic":
|
|
40
|
+
return new AnthropicClient(apiKey, model);
|
|
41
|
+
case "gemini":
|
|
42
|
+
return new GeminiClient(apiKey, model);
|
|
43
|
+
case "openrouter":
|
|
44
|
+
return new OpenRouterClient(apiKey, model);
|
|
45
|
+
case "mistral":
|
|
46
|
+
return new MistralClient(apiKey, model);
|
|
47
|
+
case "kimi":
|
|
48
|
+
return new KimiClient(apiKey, model);
|
|
49
|
+
case "groq":
|
|
50
|
+
return new GroqClient(apiKey, model);
|
|
51
|
+
default:
|
|
52
|
+
throw new Error(`Unsupported AI provider: ${provider}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
10
55
|
class OpenAIClient {
|
|
11
56
|
client;
|
|
12
57
|
model;
|
|
@@ -14,13 +59,14 @@ class OpenAIClient {
|
|
|
14
59
|
this.client = new openai_1.default({ apiKey });
|
|
15
60
|
this.model = model;
|
|
16
61
|
}
|
|
17
|
-
async analyze(prompt) {
|
|
62
|
+
async analyze(prompt, systemPrompt) {
|
|
18
63
|
const response = await this.client.chat.completions.create({
|
|
19
64
|
model: this.model,
|
|
20
65
|
messages: [
|
|
21
66
|
{
|
|
22
67
|
role: "system",
|
|
23
|
-
content:
|
|
68
|
+
content: systemPrompt ||
|
|
69
|
+
"You are a security expert analyzing web application vulnerabilities. Provide detailed, actionable insights.",
|
|
24
70
|
},
|
|
25
71
|
{ role: "user", content: prompt },
|
|
26
72
|
],
|
|
@@ -44,7 +90,7 @@ class AnthropicClient {
|
|
|
44
90
|
this.client = new sdk_1.default({ apiKey });
|
|
45
91
|
this.model = model;
|
|
46
92
|
}
|
|
47
|
-
async analyze(prompt) {
|
|
93
|
+
async analyze(prompt, systemPrompt) {
|
|
48
94
|
const response = await this.client.messages.create({
|
|
49
95
|
model: this.model,
|
|
50
96
|
max_tokens: 4096,
|
|
@@ -54,7 +100,8 @@ class AnthropicClient {
|
|
|
54
100
|
content: prompt,
|
|
55
101
|
},
|
|
56
102
|
],
|
|
57
|
-
system:
|
|
103
|
+
system: systemPrompt ||
|
|
104
|
+
"You are a security expert analyzing web application vulnerabilities. Provide detailed, actionable insights.",
|
|
58
105
|
});
|
|
59
106
|
const content = response.content[0]?.type === "text" ? response.content[0].text : "";
|
|
60
107
|
return {
|
|
@@ -67,23 +114,187 @@ class AnthropicClient {
|
|
|
67
114
|
};
|
|
68
115
|
}
|
|
69
116
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
117
|
+
class GeminiClient {
|
|
118
|
+
client;
|
|
119
|
+
model;
|
|
120
|
+
constructor(apiKey, model) {
|
|
121
|
+
this.client = new generative_ai_1.GoogleGenerativeAI(apiKey);
|
|
122
|
+
this.model = model;
|
|
74
123
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
124
|
+
async analyze(prompt, systemPrompt) {
|
|
125
|
+
const generativeModel = this.client.getGenerativeModel({ model: this.model });
|
|
126
|
+
const result = await generativeModel.generateContent([
|
|
127
|
+
systemPrompt || "You are a security expert analyzing web application vulnerabilities. Provide detailed, actionable insights.",
|
|
128
|
+
prompt
|
|
129
|
+
]);
|
|
130
|
+
const response = await result.response;
|
|
131
|
+
const content = response.text();
|
|
132
|
+
return {
|
|
133
|
+
content,
|
|
134
|
+
usage: {
|
|
135
|
+
promptTokens: response.usageMetadata?.promptTokenCount || 0,
|
|
136
|
+
completionTokens: response.usageMetadata?.candidatesTokenCount || 0,
|
|
137
|
+
totalTokens: response.usageMetadata?.totalTokenCount || 0,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
80
140
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
default
|
|
87
|
-
|
|
141
|
+
}
|
|
142
|
+
class OpenRouterClient {
|
|
143
|
+
client;
|
|
144
|
+
model;
|
|
145
|
+
constructor(apiKey, model) {
|
|
146
|
+
this.client = new openai_1.default({
|
|
147
|
+
apiKey,
|
|
148
|
+
baseURL: "https://openrouter.ai/api/v1",
|
|
149
|
+
});
|
|
150
|
+
this.model = model;
|
|
151
|
+
}
|
|
152
|
+
async analyze(prompt, systemPrompt) {
|
|
153
|
+
const response = await this.client.chat.completions.create({
|
|
154
|
+
model: this.model,
|
|
155
|
+
messages: [
|
|
156
|
+
{
|
|
157
|
+
role: "system",
|
|
158
|
+
content: systemPrompt || "You are a security expert analyzing web application vulnerabilities. Provide detailed, actionable insights.",
|
|
159
|
+
},
|
|
160
|
+
{ role: "user", content: prompt },
|
|
161
|
+
],
|
|
162
|
+
temperature: 0.3,
|
|
163
|
+
});
|
|
164
|
+
const content = response.choices[0]?.message?.content || "";
|
|
165
|
+
return {
|
|
166
|
+
content,
|
|
167
|
+
usage: {
|
|
168
|
+
promptTokens: response.usage?.prompt_tokens || 0,
|
|
169
|
+
completionTokens: response.usage?.completion_tokens || 0,
|
|
170
|
+
totalTokens: response.usage?.total_tokens || 0,
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
class MistralClient {
|
|
176
|
+
client;
|
|
177
|
+
model;
|
|
178
|
+
constructor(apiKey, model) {
|
|
179
|
+
this.client = new mistralai_1.Mistral({ apiKey });
|
|
180
|
+
this.model = model;
|
|
88
181
|
}
|
|
182
|
+
async analyze(prompt, systemPrompt) {
|
|
183
|
+
const response = await this.client.chat.complete({
|
|
184
|
+
model: this.model,
|
|
185
|
+
messages: [
|
|
186
|
+
{
|
|
187
|
+
role: "system",
|
|
188
|
+
content: systemPrompt || "You are a security expert analyzing web application vulnerabilities. Provide detailed, actionable insights.",
|
|
189
|
+
},
|
|
190
|
+
{ role: "user", content: prompt },
|
|
191
|
+
],
|
|
192
|
+
});
|
|
193
|
+
const content = typeof response.choices?.[0]?.message?.content === "string"
|
|
194
|
+
? response.choices[0].message.content
|
|
195
|
+
: "";
|
|
196
|
+
return {
|
|
197
|
+
content,
|
|
198
|
+
usage: {
|
|
199
|
+
promptTokens: response.usage?.promptTokens || 0,
|
|
200
|
+
completionTokens: response.usage?.completionTokens || 0,
|
|
201
|
+
totalTokens: response.usage?.totalTokens || 0,
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
class KimiClient {
|
|
207
|
+
client;
|
|
208
|
+
model;
|
|
209
|
+
constructor(apiKey, model) {
|
|
210
|
+
this.client = new openai_1.default({
|
|
211
|
+
apiKey,
|
|
212
|
+
baseURL: "https://api.moonshot.cn/v1",
|
|
213
|
+
});
|
|
214
|
+
this.model = model;
|
|
215
|
+
}
|
|
216
|
+
async analyze(prompt, systemPrompt) {
|
|
217
|
+
const response = await this.client.chat.completions.create({
|
|
218
|
+
model: this.model,
|
|
219
|
+
messages: [
|
|
220
|
+
{
|
|
221
|
+
role: "system",
|
|
222
|
+
content: systemPrompt || "You are a security expert analyzing web application vulnerabilities. Provide detailed, actionable insights.",
|
|
223
|
+
},
|
|
224
|
+
{ role: "user", content: prompt },
|
|
225
|
+
],
|
|
226
|
+
temperature: 0.3,
|
|
227
|
+
});
|
|
228
|
+
const content = response.choices[0]?.message?.content || "";
|
|
229
|
+
return {
|
|
230
|
+
content,
|
|
231
|
+
usage: {
|
|
232
|
+
promptTokens: response.usage?.prompt_tokens || 0,
|
|
233
|
+
completionTokens: response.usage?.completion_tokens || 0,
|
|
234
|
+
totalTokens: response.usage?.total_tokens || 0,
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
class GroqClient {
|
|
240
|
+
client;
|
|
241
|
+
model;
|
|
242
|
+
constructor(apiKey, model) {
|
|
243
|
+
this.client = new openai_1.default({
|
|
244
|
+
apiKey,
|
|
245
|
+
baseURL: "https://api.groq.com/openai/v1",
|
|
246
|
+
});
|
|
247
|
+
this.model = model;
|
|
248
|
+
}
|
|
249
|
+
async analyze(prompt, systemPrompt) {
|
|
250
|
+
const response = await this.client.chat.completions.create({
|
|
251
|
+
model: this.model,
|
|
252
|
+
messages: [
|
|
253
|
+
{
|
|
254
|
+
role: "system",
|
|
255
|
+
content: systemPrompt || "You are a security expert analyzing web application vulnerabilities. Provide detailed, actionable insights.",
|
|
256
|
+
},
|
|
257
|
+
{ role: "user", content: prompt },
|
|
258
|
+
],
|
|
259
|
+
temperature: 0.3,
|
|
260
|
+
});
|
|
261
|
+
const content = response.choices[0]?.message?.content || "";
|
|
262
|
+
return {
|
|
263
|
+
content,
|
|
264
|
+
usage: {
|
|
265
|
+
promptTokens: response.usage?.prompt_tokens || 0,
|
|
266
|
+
completionTokens: response.usage?.completion_tokens || 0,
|
|
267
|
+
totalTokens: response.usage?.total_tokens || 0,
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Generates a high-level executive summary of the scan results using AI.
|
|
274
|
+
*/
|
|
275
|
+
async function generateExecutiveSummary(client, result) {
|
|
276
|
+
const vulnSummary = result.vulnerabilities.map(v => `- [${v.severity.toUpperCase()}] ${v.title} on ${v.url}`).join("\n");
|
|
277
|
+
const prompt = `
|
|
278
|
+
Please provide a professional executive summary for a web security scan.
|
|
279
|
+
|
|
280
|
+
Target: ${result.target}
|
|
281
|
+
Scan Date: ${result.timestamp}
|
|
282
|
+
Total Vulnerabilities: ${result.summary.total}
|
|
283
|
+
Critical: ${result.summary.critical}
|
|
284
|
+
High: ${result.summary.high}
|
|
285
|
+
Medium: ${result.summary.medium}
|
|
286
|
+
Low: ${result.summary.low}
|
|
287
|
+
|
|
288
|
+
Detailed Findings:
|
|
289
|
+
${vulnSummary}
|
|
290
|
+
|
|
291
|
+
The summary should:
|
|
292
|
+
1. Briefly state the overall security posture.
|
|
293
|
+
2. Highlight the most critical risks.
|
|
294
|
+
3. Provide high-level recommendations for management.
|
|
295
|
+
4. Be concise (max 3-4 paragraphs).
|
|
296
|
+
`;
|
|
297
|
+
const systemPrompt = "You are a senior cybersecurity consultant writing for a non-technical executive audience. Focus on business risk and impact.";
|
|
298
|
+
const response = await client.analyze(prompt, systemPrompt);
|
|
299
|
+
return response.content;
|
|
89
300
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AIClient } from "./ai-client";
|
|
2
|
+
export type PayloadType = "xss" | "sqli" | "cmdi" | "lfi";
|
|
3
|
+
export interface ContextInfo {
|
|
4
|
+
htmlContext?: string;
|
|
5
|
+
tagName?: string;
|
|
6
|
+
attributeName?: string;
|
|
7
|
+
parameterName: string;
|
|
8
|
+
url: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class PayloadGenerator {
|
|
11
|
+
private aiClient;
|
|
12
|
+
constructor(aiClient: AIClient);
|
|
13
|
+
/**
|
|
14
|
+
* Generates a list of contextual payloads based on the provided HTML context.
|
|
15
|
+
*/
|
|
16
|
+
generatePayloads(type: PayloadType, context: ContextInfo): Promise<string[]>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PayloadGenerator = void 0;
|
|
4
|
+
class PayloadGenerator {
|
|
5
|
+
aiClient;
|
|
6
|
+
constructor(aiClient) {
|
|
7
|
+
this.aiClient = aiClient;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generates a list of contextual payloads based on the provided HTML context.
|
|
11
|
+
*/
|
|
12
|
+
async generatePayloads(type, context) {
|
|
13
|
+
const systemPrompt = `You are an expert penetration tester. Your task is to generate 5 highly effective, specialized payloads to test for ${type.toUpperCase()} vulnerabilities.
|
|
14
|
+
Focus on bypass techniques relevant to the provided HTML/parameter context.
|
|
15
|
+
Format your response as a simple JSON array of strings: ["payload1", "payload2", ...]
|
|
16
|
+
Do not include any explanations, just the JSON array.`;
|
|
17
|
+
const prompt = `
|
|
18
|
+
Generate 5 ${type.toUpperCase()} payloads for:
|
|
19
|
+
Parameter: ${context.parameterName}
|
|
20
|
+
URL: ${context.url}
|
|
21
|
+
${context.htmlContext ? `HTML Context: ${context.htmlContext}` : ""}
|
|
22
|
+
${context.tagName ? `Inside Tag: ${context.tagName}` : ""}
|
|
23
|
+
${context.attributeName ? `Inside Attribute: ${context.attributeName}` : ""}
|
|
24
|
+
|
|
25
|
+
Consider:
|
|
26
|
+
1. Filter bypasses (WAF, sanitizers).
|
|
27
|
+
2. Escape sequences if inside a string or attribute.
|
|
28
|
+
3. Breaking out of tags if applicable.
|
|
29
|
+
4. Non-standard encoding (URL/HTML entities) if likely needed.
|
|
30
|
+
`;
|
|
31
|
+
try {
|
|
32
|
+
const response = await this.aiClient.analyze(prompt, systemPrompt);
|
|
33
|
+
const content = response.content.trim();
|
|
34
|
+
// Try to parse JSON array from the response
|
|
35
|
+
const match = content.match(/\[.*\]/s);
|
|
36
|
+
if (match) {
|
|
37
|
+
const payloads = JSON.parse(match[0]);
|
|
38
|
+
if (Array.isArray(payloads)) {
|
|
39
|
+
return payloads.map(p => String(p));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Fallback: split by newlines if JSON parsing fails
|
|
43
|
+
return content.split("\n")
|
|
44
|
+
.map(line => line.replace(/^[\d.-]\s*/, "").trim())
|
|
45
|
+
.filter(line => line.length > 0)
|
|
46
|
+
.slice(0, 5);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error(`Error generating AI payloads: ${error.message}`);
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.PayloadGenerator = PayloadGenerator;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const AiProviderNameSchema: z.ZodEnum<["openai", "anthropic", "gemini", "openrouter", "mistral", "kimi", "groq"]>;
|
|
3
|
+
export declare const ReportFormatSchema: z.ZodEnum<["word", "txt", "json"]>;
|
|
4
|
+
export declare const SeverityThresholdSchema: z.ZodEnum<["info", "low", "medium", "high", "critical"]>;
|
|
5
|
+
export declare const ScanProfileSchema: z.ZodObject<{
|
|
6
|
+
depth: z.ZodNumber;
|
|
7
|
+
timeout: z.ZodNumber;
|
|
8
|
+
maxPages: z.ZodNumber;
|
|
9
|
+
maxLinksPerPage: z.ZodNumber;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
depth: number;
|
|
12
|
+
timeout: number;
|
|
13
|
+
maxPages: number;
|
|
14
|
+
maxLinksPerPage: number;
|
|
15
|
+
}, {
|
|
16
|
+
depth: number;
|
|
17
|
+
timeout: number;
|
|
18
|
+
maxPages: number;
|
|
19
|
+
maxLinksPerPage: number;
|
|
20
|
+
}>;
|
|
21
|
+
export type ScanProfile = z.infer<typeof ScanProfileSchema>;
|
|
22
|
+
export declare const defaultScanProfiles: Record<string, ScanProfile>;
|
|
23
|
+
export declare const ConfigSchema: z.ZodObject<{
|
|
24
|
+
ai: z.ZodObject<{
|
|
25
|
+
provider: z.ZodDefault<z.ZodEnum<["openai", "anthropic", "gemini", "openrouter", "mistral", "kimi", "groq"]>>;
|
|
26
|
+
apiKey: z.ZodDefault<z.ZodString>;
|
|
27
|
+
defaultModel: z.ZodDefault<z.ZodString>;
|
|
28
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
provider: "openai" | "anthropic" | "gemini" | "openrouter" | "mistral" | "kimi" | "groq";
|
|
31
|
+
apiKey: string;
|
|
32
|
+
defaultModel: string;
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
}, {
|
|
35
|
+
provider?: "openai" | "anthropic" | "gemini" | "openrouter" | "mistral" | "kimi" | "groq" | undefined;
|
|
36
|
+
apiKey?: string | undefined;
|
|
37
|
+
defaultModel?: string | undefined;
|
|
38
|
+
enabled?: boolean | undefined;
|
|
39
|
+
}>;
|
|
40
|
+
scan: z.ZodObject<{
|
|
41
|
+
defaultTimeout: z.ZodDefault<z.ZodNumber>;
|
|
42
|
+
maxThreads: z.ZodDefault<z.ZodNumber>;
|
|
43
|
+
userAgent: z.ZodDefault<z.ZodString>;
|
|
44
|
+
followRedirects: z.ZodDefault<z.ZodBoolean>;
|
|
45
|
+
verifySSL: z.ZodDefault<z.ZodBoolean>;
|
|
46
|
+
rateLimitPerSecond: z.ZodDefault<z.ZodNumber>;
|
|
47
|
+
strictScope: z.ZodDefault<z.ZodBoolean>;
|
|
48
|
+
profiles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
49
|
+
depth: z.ZodNumber;
|
|
50
|
+
timeout: z.ZodNumber;
|
|
51
|
+
maxPages: z.ZodNumber;
|
|
52
|
+
maxLinksPerPage: z.ZodNumber;
|
|
53
|
+
}, "strip", z.ZodTypeAny, {
|
|
54
|
+
depth: number;
|
|
55
|
+
timeout: number;
|
|
56
|
+
maxPages: number;
|
|
57
|
+
maxLinksPerPage: number;
|
|
58
|
+
}, {
|
|
59
|
+
depth: number;
|
|
60
|
+
timeout: number;
|
|
61
|
+
maxPages: number;
|
|
62
|
+
maxLinksPerPage: number;
|
|
63
|
+
}>>>;
|
|
64
|
+
defaultProfile: z.ZodDefault<z.ZodString>;
|
|
65
|
+
}, "strip", z.ZodTypeAny, {
|
|
66
|
+
defaultTimeout: number;
|
|
67
|
+
maxThreads: number;
|
|
68
|
+
userAgent: string;
|
|
69
|
+
followRedirects: boolean;
|
|
70
|
+
verifySSL: boolean;
|
|
71
|
+
rateLimitPerSecond: number;
|
|
72
|
+
strictScope: boolean;
|
|
73
|
+
profiles: Record<string, {
|
|
74
|
+
depth: number;
|
|
75
|
+
timeout: number;
|
|
76
|
+
maxPages: number;
|
|
77
|
+
maxLinksPerPage: number;
|
|
78
|
+
}>;
|
|
79
|
+
defaultProfile: string;
|
|
80
|
+
}, {
|
|
81
|
+
defaultTimeout?: number | undefined;
|
|
82
|
+
maxThreads?: number | undefined;
|
|
83
|
+
userAgent?: string | undefined;
|
|
84
|
+
followRedirects?: boolean | undefined;
|
|
85
|
+
verifySSL?: boolean | undefined;
|
|
86
|
+
rateLimitPerSecond?: number | undefined;
|
|
87
|
+
strictScope?: boolean | undefined;
|
|
88
|
+
profiles?: Record<string, {
|
|
89
|
+
depth: number;
|
|
90
|
+
timeout: number;
|
|
91
|
+
maxPages: number;
|
|
92
|
+
maxLinksPerPage: number;
|
|
93
|
+
}> | undefined;
|
|
94
|
+
defaultProfile?: string | undefined;
|
|
95
|
+
}>;
|
|
96
|
+
report: z.ZodObject<{
|
|
97
|
+
defaultFormat: z.ZodDefault<z.ZodEnum<["word", "txt", "json"]>>;
|
|
98
|
+
companyName: z.ZodDefault<z.ZodString>;
|
|
99
|
+
includeScreenshots: z.ZodDefault<z.ZodBoolean>;
|
|
100
|
+
severityThreshold: z.ZodDefault<z.ZodEnum<["info", "low", "medium", "high", "critical"]>>;
|
|
101
|
+
}, "strip", z.ZodTypeAny, {
|
|
102
|
+
defaultFormat: "word" | "txt" | "json";
|
|
103
|
+
companyName: string;
|
|
104
|
+
includeScreenshots: boolean;
|
|
105
|
+
severityThreshold: "info" | "low" | "medium" | "high" | "critical";
|
|
106
|
+
}, {
|
|
107
|
+
defaultFormat?: "word" | "txt" | "json" | undefined;
|
|
108
|
+
companyName?: string | undefined;
|
|
109
|
+
includeScreenshots?: boolean | undefined;
|
|
110
|
+
severityThreshold?: "info" | "low" | "medium" | "high" | "critical" | undefined;
|
|
111
|
+
}>;
|
|
112
|
+
skills: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
113
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
114
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
115
|
+
}, "strip", z.ZodTypeAny, {
|
|
116
|
+
enabled: boolean;
|
|
117
|
+
timeout?: number | undefined;
|
|
118
|
+
}, {
|
|
119
|
+
timeout?: number | undefined;
|
|
120
|
+
enabled?: boolean | undefined;
|
|
121
|
+
}>>>;
|
|
122
|
+
proxy: z.ZodOptional<z.ZodString>;
|
|
123
|
+
}, "strip", z.ZodTypeAny, {
|
|
124
|
+
ai: {
|
|
125
|
+
provider: "openai" | "anthropic" | "gemini" | "openrouter" | "mistral" | "kimi" | "groq";
|
|
126
|
+
apiKey: string;
|
|
127
|
+
defaultModel: string;
|
|
128
|
+
enabled: boolean;
|
|
129
|
+
};
|
|
130
|
+
scan: {
|
|
131
|
+
defaultTimeout: number;
|
|
132
|
+
maxThreads: number;
|
|
133
|
+
userAgent: string;
|
|
134
|
+
followRedirects: boolean;
|
|
135
|
+
verifySSL: boolean;
|
|
136
|
+
rateLimitPerSecond: number;
|
|
137
|
+
strictScope: boolean;
|
|
138
|
+
profiles: Record<string, {
|
|
139
|
+
depth: number;
|
|
140
|
+
timeout: number;
|
|
141
|
+
maxPages: number;
|
|
142
|
+
maxLinksPerPage: number;
|
|
143
|
+
}>;
|
|
144
|
+
defaultProfile: string;
|
|
145
|
+
};
|
|
146
|
+
report: {
|
|
147
|
+
defaultFormat: "word" | "txt" | "json";
|
|
148
|
+
companyName: string;
|
|
149
|
+
includeScreenshots: boolean;
|
|
150
|
+
severityThreshold: "info" | "low" | "medium" | "high" | "critical";
|
|
151
|
+
};
|
|
152
|
+
skills: Record<string, {
|
|
153
|
+
enabled: boolean;
|
|
154
|
+
timeout?: number | undefined;
|
|
155
|
+
}>;
|
|
156
|
+
proxy?: string | undefined;
|
|
157
|
+
}, {
|
|
158
|
+
ai: {
|
|
159
|
+
provider?: "openai" | "anthropic" | "gemini" | "openrouter" | "mistral" | "kimi" | "groq" | undefined;
|
|
160
|
+
apiKey?: string | undefined;
|
|
161
|
+
defaultModel?: string | undefined;
|
|
162
|
+
enabled?: boolean | undefined;
|
|
163
|
+
};
|
|
164
|
+
scan: {
|
|
165
|
+
defaultTimeout?: number | undefined;
|
|
166
|
+
maxThreads?: number | undefined;
|
|
167
|
+
userAgent?: string | undefined;
|
|
168
|
+
followRedirects?: boolean | undefined;
|
|
169
|
+
verifySSL?: boolean | undefined;
|
|
170
|
+
rateLimitPerSecond?: number | undefined;
|
|
171
|
+
strictScope?: boolean | undefined;
|
|
172
|
+
profiles?: Record<string, {
|
|
173
|
+
depth: number;
|
|
174
|
+
timeout: number;
|
|
175
|
+
maxPages: number;
|
|
176
|
+
maxLinksPerPage: number;
|
|
177
|
+
}> | undefined;
|
|
178
|
+
defaultProfile?: string | undefined;
|
|
179
|
+
};
|
|
180
|
+
report: {
|
|
181
|
+
defaultFormat?: "word" | "txt" | "json" | undefined;
|
|
182
|
+
companyName?: string | undefined;
|
|
183
|
+
includeScreenshots?: boolean | undefined;
|
|
184
|
+
severityThreshold?: "info" | "low" | "medium" | "high" | "critical" | undefined;
|
|
185
|
+
};
|
|
186
|
+
skills?: Record<string, {
|
|
187
|
+
timeout?: number | undefined;
|
|
188
|
+
enabled?: boolean | undefined;
|
|
189
|
+
}> | undefined;
|
|
190
|
+
proxy?: string | undefined;
|
|
191
|
+
}>;
|
|
192
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
193
|
+
export type AiProviderName = z.infer<typeof AiProviderNameSchema>;
|
|
194
|
+
export type ReportFormat = z.infer<typeof ReportFormatSchema>;
|
|
195
|
+
export declare function validateConfig(config: unknown): Config;
|
|
196
|
+
export declare function validateScanProfile(profile: unknown): ScanProfile;
|
|
197
|
+
export { defaultScanProfiles as scanProfiles };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanProfiles = exports.ConfigSchema = exports.defaultScanProfiles = exports.ScanProfileSchema = exports.SeverityThresholdSchema = exports.ReportFormatSchema = exports.AiProviderNameSchema = void 0;
|
|
4
|
+
exports.validateConfig = validateConfig;
|
|
5
|
+
exports.validateScanProfile = validateScanProfile;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
// ─── Zod Schemas ───────────────────────────────────────────────────
|
|
8
|
+
exports.AiProviderNameSchema = zod_1.z.enum([
|
|
9
|
+
"openai",
|
|
10
|
+
"anthropic",
|
|
11
|
+
"gemini",
|
|
12
|
+
"openrouter",
|
|
13
|
+
"mistral",
|
|
14
|
+
"kimi",
|
|
15
|
+
"groq",
|
|
16
|
+
]);
|
|
17
|
+
exports.ReportFormatSchema = zod_1.z.enum(["word", "txt", "json"]);
|
|
18
|
+
exports.SeverityThresholdSchema = zod_1.z.enum(["info", "low", "medium", "high", "critical"]);
|
|
19
|
+
exports.ScanProfileSchema = zod_1.z.object({
|
|
20
|
+
depth: zod_1.z.number().int().min(1).max(5),
|
|
21
|
+
timeout: zod_1.z.number().int().min(1000),
|
|
22
|
+
maxPages: zod_1.z.number().int().min(1),
|
|
23
|
+
maxLinksPerPage: zod_1.z.number().int().min(1),
|
|
24
|
+
});
|
|
25
|
+
// Default scan profiles
|
|
26
|
+
exports.defaultScanProfiles = {
|
|
27
|
+
quick: { depth: 1, timeout: 15000, maxPages: 10, maxLinksPerPage: 20 },
|
|
28
|
+
balanced: { depth: 2, timeout: 30000, maxPages: 30, maxLinksPerPage: 50 },
|
|
29
|
+
deep: { depth: 3, timeout: 60000, maxPages: 100, maxLinksPerPage: 100 },
|
|
30
|
+
};
|
|
31
|
+
exports.scanProfiles = exports.defaultScanProfiles;
|
|
32
|
+
exports.ConfigSchema = zod_1.z.object({
|
|
33
|
+
ai: zod_1.z.object({
|
|
34
|
+
provider: exports.AiProviderNameSchema.default("openai"),
|
|
35
|
+
apiKey: zod_1.z.string().default(""),
|
|
36
|
+
defaultModel: zod_1.z.string().default("gpt-4"),
|
|
37
|
+
enabled: zod_1.z.boolean().default(false),
|
|
38
|
+
}),
|
|
39
|
+
scan: zod_1.z.object({
|
|
40
|
+
defaultTimeout: zod_1.z.number().int().min(1000).default(30000),
|
|
41
|
+
maxThreads: zod_1.z.number().int().min(1).max(20).default(5),
|
|
42
|
+
userAgent: zod_1.z.string().default("KramScan/0.1.1"),
|
|
43
|
+
followRedirects: zod_1.z.boolean().default(true),
|
|
44
|
+
verifySSL: zod_1.z.boolean().default(true),
|
|
45
|
+
rateLimitPerSecond: zod_1.z.number().int().min(1).max(100).default(5),
|
|
46
|
+
strictScope: zod_1.z.boolean().default(true),
|
|
47
|
+
profiles: zod_1.z.record(exports.ScanProfileSchema).default(exports.defaultScanProfiles),
|
|
48
|
+
defaultProfile: zod_1.z.string().default("balanced"),
|
|
49
|
+
}),
|
|
50
|
+
report: zod_1.z.object({
|
|
51
|
+
defaultFormat: exports.ReportFormatSchema.default("word"),
|
|
52
|
+
companyName: zod_1.z.string().default("Your Company"),
|
|
53
|
+
includeScreenshots: zod_1.z.boolean().default(false),
|
|
54
|
+
severityThreshold: exports.SeverityThresholdSchema.default("low"),
|
|
55
|
+
}),
|
|
56
|
+
skills: zod_1.z.record(zod_1.z.object({
|
|
57
|
+
enabled: zod_1.z.boolean().default(true),
|
|
58
|
+
timeout: zod_1.z.number().int().optional(),
|
|
59
|
+
})).default({}),
|
|
60
|
+
proxy: zod_1.z.string().optional(),
|
|
61
|
+
});
|
|
62
|
+
// Validation function
|
|
63
|
+
function validateConfig(config) {
|
|
64
|
+
return exports.ConfigSchema.parse(config);
|
|
65
|
+
}
|
|
66
|
+
function validateScanProfile(profile) {
|
|
67
|
+
return exports.ScanProfileSchema.parse(profile);
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|