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
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Web Scan Skill
|
|
4
|
+
* Comprehensive web application security scanner as an AI-callable skill
|
|
5
|
+
* Tests for XSS, SQL injection, CSRF, and security header vulnerabilities
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.WebScanSkill = void 0;
|
|
9
|
+
const scanner_1 = require("../../core/scanner");
|
|
10
|
+
const logger_1 = require("../../utils/logger");
|
|
11
|
+
class WebScanSkill {
|
|
12
|
+
id = "web_scan";
|
|
13
|
+
name = "Web Scan";
|
|
14
|
+
description = "Performs a comprehensive security scan of a web application. Tests for XSS, SQL injection, CSRF, and security header misconfigurations.";
|
|
15
|
+
tags = ["scanning", "web", "security", "vulnerability"];
|
|
16
|
+
requiresConfirmation = true;
|
|
17
|
+
riskLevel = "medium";
|
|
18
|
+
estimatedDuration = 60; // seconds
|
|
19
|
+
toolDefinition = {
|
|
20
|
+
name: "web_scan",
|
|
21
|
+
description: "Scan a web application for security vulnerabilities including XSS, SQL injection, CSRF, and security headers",
|
|
22
|
+
parameters: [
|
|
23
|
+
{
|
|
24
|
+
name: "targetUrl",
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "The URL of the web application to scan (e.g., https://example.com)",
|
|
27
|
+
required: true,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "depth",
|
|
31
|
+
type: "number",
|
|
32
|
+
description: "How many levels deep to crawl (1-5). Higher values scan more pages but take longer.",
|
|
33
|
+
required: false,
|
|
34
|
+
default: 2,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "timeout",
|
|
38
|
+
type: "number",
|
|
39
|
+
description: "Request timeout in milliseconds (10000-120000)",
|
|
40
|
+
required: false,
|
|
41
|
+
default: 30000,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "headless",
|
|
45
|
+
type: "boolean",
|
|
46
|
+
description: "Run browser in headless mode (no visible window)",
|
|
47
|
+
required: false,
|
|
48
|
+
default: true,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "maxPages",
|
|
52
|
+
type: "number",
|
|
53
|
+
description: "Maximum pages to crawl before stopping",
|
|
54
|
+
required: false,
|
|
55
|
+
default: 30,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "maxLinksPerPage",
|
|
59
|
+
type: "number",
|
|
60
|
+
description: "Maximum links to follow per page",
|
|
61
|
+
required: false,
|
|
62
|
+
default: 50,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "include",
|
|
66
|
+
type: "array",
|
|
67
|
+
description: "Only include URLs matching these regex patterns (strings)",
|
|
68
|
+
required: false,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "exclude",
|
|
72
|
+
type: "array",
|
|
73
|
+
description: "Exclude URLs matching these regex patterns (strings)",
|
|
74
|
+
required: false,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
validateParameters(params) {
|
|
79
|
+
const errors = [];
|
|
80
|
+
// Validate targetUrl
|
|
81
|
+
if (!params.targetUrl) {
|
|
82
|
+
errors.push("targetUrl is required");
|
|
83
|
+
}
|
|
84
|
+
else if (typeof params.targetUrl !== "string") {
|
|
85
|
+
errors.push("targetUrl must be a string");
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
try {
|
|
89
|
+
const url = new URL(params.targetUrl);
|
|
90
|
+
if (!["http:", "https:"].includes(url.protocol)) {
|
|
91
|
+
errors.push("targetUrl must use HTTP or HTTPS protocol");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
errors.push("targetUrl must be a valid URL");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Validate depth
|
|
99
|
+
if (params.depth !== undefined) {
|
|
100
|
+
const depth = Number(params.depth);
|
|
101
|
+
if (isNaN(depth) || depth < 1 || depth > 5) {
|
|
102
|
+
errors.push("depth must be a number between 1 and 5");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Validate timeout
|
|
106
|
+
if (params.timeout !== undefined) {
|
|
107
|
+
const timeout = Number(params.timeout);
|
|
108
|
+
if (isNaN(timeout) || timeout < 10000 || timeout > 120000) {
|
|
109
|
+
errors.push("timeout must be a number between 10000 and 120000");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (params.maxPages !== undefined) {
|
|
113
|
+
const maxPages = Number(params.maxPages);
|
|
114
|
+
if (isNaN(maxPages) || maxPages < 1 || maxPages > 10000) {
|
|
115
|
+
errors.push("maxPages must be a positive number");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (params.maxLinksPerPage !== undefined) {
|
|
119
|
+
const maxLinks = Number(params.maxLinksPerPage);
|
|
120
|
+
if (isNaN(maxLinks) || maxLinks < 1 || maxLinks > 10000) {
|
|
121
|
+
errors.push("maxLinksPerPage must be a positive number");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
valid: errors.length === 0,
|
|
126
|
+
errors,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
async execute(params, context) {
|
|
130
|
+
const targetUrl = params.targetUrl;
|
|
131
|
+
const depth = params.depth ?? 2;
|
|
132
|
+
const timeout = params.timeout ?? 30000;
|
|
133
|
+
const headless = params.headless ?? true;
|
|
134
|
+
const maxPages = params.maxPages ?? 30;
|
|
135
|
+
const maxLinksPerPage = params.maxLinksPerPage ?? 50;
|
|
136
|
+
const include = params.include;
|
|
137
|
+
const exclude = params.exclude;
|
|
138
|
+
logger_1.logger.info(`Starting web scan of ${targetUrl}`);
|
|
139
|
+
const scanner = new scanner_1.Scanner();
|
|
140
|
+
try {
|
|
141
|
+
const scanResult = await scanner.scan(targetUrl, {
|
|
142
|
+
depth,
|
|
143
|
+
timeout,
|
|
144
|
+
headless,
|
|
145
|
+
maxPages,
|
|
146
|
+
maxLinksPerPage,
|
|
147
|
+
include,
|
|
148
|
+
exclude,
|
|
149
|
+
});
|
|
150
|
+
// Convert vulnerabilities to findings
|
|
151
|
+
const findings = scanResult.vulnerabilities.map((vuln) => ({
|
|
152
|
+
id: `${vuln.type}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
153
|
+
skillId: this.id,
|
|
154
|
+
title: vuln.title,
|
|
155
|
+
severity: vuln.severity,
|
|
156
|
+
description: vuln.description,
|
|
157
|
+
evidence: vuln.evidence,
|
|
158
|
+
recommendation: vuln.remediation,
|
|
159
|
+
references: [],
|
|
160
|
+
metadata: {
|
|
161
|
+
url: vuln.url,
|
|
162
|
+
type: vuln.type,
|
|
163
|
+
cwe: vuln.cwe,
|
|
164
|
+
},
|
|
165
|
+
}));
|
|
166
|
+
logger_1.logger.success(`Scan complete. Found ${findings.length} vulnerabilities.`);
|
|
167
|
+
return {
|
|
168
|
+
skillId: this.id,
|
|
169
|
+
findings,
|
|
170
|
+
metadata: {
|
|
171
|
+
target: scanResult.target,
|
|
172
|
+
timestamp: scanResult.timestamp,
|
|
173
|
+
duration: scanResult.duration,
|
|
174
|
+
summary: scanResult.summary,
|
|
175
|
+
crawledUrls: scanResult.metadata.crawledUrls,
|
|
176
|
+
testedForms: scanResult.metadata.testedForms,
|
|
177
|
+
requestsMade: scanResult.metadata.requestsMade,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
183
|
+
logger_1.logger.error(`Scan failed: ${errorMessage}`);
|
|
184
|
+
return {
|
|
185
|
+
skillId: this.id,
|
|
186
|
+
findings: [],
|
|
187
|
+
metadata: {
|
|
188
|
+
error: errorMessage,
|
|
189
|
+
target: targetUrl,
|
|
190
|
+
timestamp: new Date().toISOString(),
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
finally {
|
|
195
|
+
await scanner.close();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async run() {
|
|
199
|
+
// This method is required by Skill interface but not used in agent context
|
|
200
|
+
throw new Error("Use execute() method with AgentContext for web scan skill");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
exports.WebScanSkill = WebScanSkill;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for the KramScan AI Agent system
|
|
3
|
+
* Defines interfaces for skills, tool calling, conversation context, and agent responses
|
|
4
|
+
*/
|
|
5
|
+
export type Severity = "info" | "low" | "medium" | "high" | "critical";
|
|
6
|
+
export interface Finding {
|
|
7
|
+
id: string;
|
|
8
|
+
skillId: string;
|
|
9
|
+
title: string;
|
|
10
|
+
severity: Severity;
|
|
11
|
+
description: string;
|
|
12
|
+
evidence?: string;
|
|
13
|
+
recommendation?: string;
|
|
14
|
+
references?: string[];
|
|
15
|
+
metadata?: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export interface SkillMetadata {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
tags: string[];
|
|
22
|
+
category?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface SkillResult {
|
|
25
|
+
skillId: string;
|
|
26
|
+
findings: Finding[];
|
|
27
|
+
metadata?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
export interface Skill {
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
tags: string[];
|
|
34
|
+
run(context: SkillContext): Promise<SkillResult>;
|
|
35
|
+
}
|
|
36
|
+
export interface SkillContext {
|
|
37
|
+
targetUrl: string;
|
|
38
|
+
timeoutSeconds: number;
|
|
39
|
+
logger: {
|
|
40
|
+
info(message: string): void;
|
|
41
|
+
warn(message: string): void;
|
|
42
|
+
error(message: string): void;
|
|
43
|
+
};
|
|
44
|
+
http: {
|
|
45
|
+
get: <T = unknown>(url: string) => Promise<{
|
|
46
|
+
data: T;
|
|
47
|
+
headers: Record<string, string>;
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export interface ToolParameter {
|
|
52
|
+
name: string;
|
|
53
|
+
type: "string" | "number" | "boolean" | "array" | "object";
|
|
54
|
+
description: string;
|
|
55
|
+
required: boolean;
|
|
56
|
+
default?: unknown;
|
|
57
|
+
enum?: string[];
|
|
58
|
+
}
|
|
59
|
+
export interface ToolDefinition {
|
|
60
|
+
name: string;
|
|
61
|
+
description: string;
|
|
62
|
+
parameters: ToolParameter[];
|
|
63
|
+
}
|
|
64
|
+
export interface ToolCall {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
arguments: Record<string, unknown>;
|
|
68
|
+
}
|
|
69
|
+
export interface ToolCallResult {
|
|
70
|
+
toolCallId: string;
|
|
71
|
+
success: boolean;
|
|
72
|
+
result?: SkillResult | unknown;
|
|
73
|
+
error?: string;
|
|
74
|
+
executionTime: number;
|
|
75
|
+
}
|
|
76
|
+
export interface ConversationMessage {
|
|
77
|
+
id: string;
|
|
78
|
+
role: "user" | "assistant" | "system" | "tool";
|
|
79
|
+
content: string;
|
|
80
|
+
timestamp: Date;
|
|
81
|
+
toolCalls?: ToolCall[];
|
|
82
|
+
toolCallResults?: ToolCallResult[];
|
|
83
|
+
}
|
|
84
|
+
export interface AgentContext {
|
|
85
|
+
sessionId: string;
|
|
86
|
+
userId: string;
|
|
87
|
+
startTime: Date;
|
|
88
|
+
currentTarget?: string;
|
|
89
|
+
lastScanResults?: SkillResult;
|
|
90
|
+
workingDirectory: string;
|
|
91
|
+
environment: {
|
|
92
|
+
nodeVersion: string;
|
|
93
|
+
platform: string;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export interface AgentResponse {
|
|
97
|
+
message: string;
|
|
98
|
+
toolCalls?: ToolCall[];
|
|
99
|
+
toolCallResults?: ToolCallResult[];
|
|
100
|
+
requiresConfirmation: boolean;
|
|
101
|
+
pendingAction?: {
|
|
102
|
+
toolName: string;
|
|
103
|
+
description: string;
|
|
104
|
+
parameters: Record<string, unknown>;
|
|
105
|
+
risk: "low" | "medium" | "high";
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export interface AgentSkill extends Skill {
|
|
109
|
+
/** Tool definition for AI function calling */
|
|
110
|
+
toolDefinition: ToolDefinition;
|
|
111
|
+
/** Whether this skill requires user confirmation before execution */
|
|
112
|
+
requiresConfirmation: boolean;
|
|
113
|
+
/** Risk level of the skill */
|
|
114
|
+
riskLevel: "low" | "medium" | "high";
|
|
115
|
+
/** Estimated execution time in seconds */
|
|
116
|
+
estimatedDuration: number;
|
|
117
|
+
/** Validate parameters before execution */
|
|
118
|
+
validateParameters(params: Record<string, unknown>): {
|
|
119
|
+
valid: boolean;
|
|
120
|
+
errors: string[];
|
|
121
|
+
};
|
|
122
|
+
/** Execute the skill with given parameters */
|
|
123
|
+
execute(params: Record<string, unknown>, context: AgentContext): Promise<SkillResult>;
|
|
124
|
+
}
|
|
125
|
+
export interface ConfirmationPrompt {
|
|
126
|
+
action: string;
|
|
127
|
+
description: string;
|
|
128
|
+
parameters: Record<string, unknown>;
|
|
129
|
+
risk: "low" | "medium" | "high";
|
|
130
|
+
estimatedTime: string;
|
|
131
|
+
}
|
|
132
|
+
export interface AgentConfig {
|
|
133
|
+
maxConversationHistory: number;
|
|
134
|
+
enableConfirmation: boolean;
|
|
135
|
+
autoConfirmLowRisk: boolean;
|
|
136
|
+
maxTokensPerRequest: number;
|
|
137
|
+
temperature: number;
|
|
138
|
+
model: string;
|
|
139
|
+
systemPrompt: string;
|
|
140
|
+
}
|
|
141
|
+
export declare const DEFAULT_AGENT_CONFIG: AgentConfig;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Core types for the KramScan AI Agent system
|
|
4
|
+
* Defines interfaces for skills, tool calling, conversation context, and agent responses
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.DEFAULT_AGENT_CONFIG = void 0;
|
|
8
|
+
exports.DEFAULT_AGENT_CONFIG = {
|
|
9
|
+
maxConversationHistory: 20,
|
|
10
|
+
enableConfirmation: true,
|
|
11
|
+
autoConfirmLowRisk: false,
|
|
12
|
+
maxTokensPerRequest: 4096,
|
|
13
|
+
temperature: 0.3,
|
|
14
|
+
model: "claude-3-opus-4-6",
|
|
15
|
+
systemPrompt: ``, // Will be loaded from prompts/system.ts
|
|
16
|
+
};
|
package/dist/cli.d.ts
CHANGED