mcp-wordpress 2.2.0 → 2.4.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 +503 -0
- package/dist/client/api.d.ts +90 -0
- package/dist/client/api.d.ts.map +1 -1
- package/dist/client/api.js +90 -0
- package/dist/client/api.js.map +1 -1
- package/dist/security/AISecurityScanner.d.ts +175 -0
- package/dist/security/AISecurityScanner.d.ts.map +1 -0
- package/dist/security/AISecurityScanner.js +645 -0
- package/dist/security/AISecurityScanner.js.map +1 -0
- package/dist/security/AutomatedRemediation.d.ts +145 -0
- package/dist/security/AutomatedRemediation.d.ts.map +1 -0
- package/dist/security/AutomatedRemediation.js +535 -0
- package/dist/security/AutomatedRemediation.js.map +1 -0
- package/dist/security/SecurityCIPipeline.d.ts +213 -0
- package/dist/security/SecurityCIPipeline.d.ts.map +1 -0
- package/dist/security/SecurityCIPipeline.js +684 -0
- package/dist/security/SecurityCIPipeline.js.map +1 -0
- package/dist/security/SecurityConfigManager.d.ts +294 -0
- package/dist/security/SecurityConfigManager.d.ts.map +1 -0
- package/dist/security/SecurityConfigManager.js +553 -0
- package/dist/security/SecurityConfigManager.js.map +1 -0
- package/dist/security/SecurityMonitoring.d.ts +245 -0
- package/dist/security/SecurityMonitoring.d.ts.map +1 -0
- package/dist/security/SecurityMonitoring.js +596 -0
- package/dist/security/SecurityMonitoring.js.map +1 -0
- package/dist/security/SecurityReviewer.d.ts +168 -0
- package/dist/security/SecurityReviewer.d.ts.map +1 -0
- package/dist/security/SecurityReviewer.js +683 -0
- package/dist/security/SecurityReviewer.js.map +1 -0
- package/dist/security/index.d.ts +182 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +189 -0
- package/dist/security/index.js.map +1 -0
- package/dist/tools/media.d.ts +43 -4
- package/dist/tools/media.d.ts.map +1 -1
- package/dist/tools/media.js +43 -4
- package/dist/tools/media.js.map +1 -1
- package/dist/tools/posts.d.ts +225 -4
- package/dist/tools/posts.d.ts.map +1 -1
- package/dist/tools/posts.js +225 -4
- package/dist/tools/posts.js.map +1 -1
- package/docs/DOCKER_PUBLISHING_TROUBLESHOOTING.md +233 -0
- package/docs/PUBLISHING-TROUBLESHOOTING.md +227 -0
- package/docs/api/README.md +53 -11
- package/docs/api/openapi.json +10 -10
- package/docs/api/summary.json +1 -1
- package/docs/api/tools/wp_create_post.md +9 -3
- package/docs/api/tools/wp_delete_post.md +2 -3
- package/docs/api/tools/wp_get_current_user.md +7 -1
- package/docs/api/tools/wp_get_post.md +2 -3
- package/docs/api/tools/wp_get_post_revisions.md +1 -1
- package/docs/api/tools/wp_list_posts.md +10 -3
- package/docs/api/tools/wp_list_users.md +8 -1
- package/docs/api/tools/wp_search_site.md +8 -1
- package/docs/api/tools/wp_test_auth.md +8 -1
- package/docs/api/tools/wp_update_post.md +2 -3
- package/docs/examples/docker-production.md +801 -0
- package/docs/examples/multi-site-setup.md +575 -0
- package/docs/examples/single-site-setup.md +390 -0
- package/docs/examples/use-case-workflows.md +469 -0
- package/package.json +11 -3
- package/src/client/api.ts +90 -0
- package/src/security/AISecurityScanner.ts +780 -0
- package/src/security/AutomatedRemediation.ts +665 -0
- package/src/security/SecurityCIPipeline.ts +969 -0
- package/src/security/SecurityConfigManager.ts +829 -0
- package/src/security/SecurityMonitoring.ts +841 -0
- package/src/security/SecurityReviewer.ts +855 -0
- package/src/security/index.ts +249 -0
- package/src/tools/media.ts +43 -4
- package/src/tools/posts.ts +225 -4
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI-Powered Security Scanner
|
|
3
|
+
* Provides intelligent vulnerability detection and automated remediation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as fs from "fs/promises";
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
import { SecurityUtils } from "./SecurityConfig";
|
|
9
|
+
import { SecurityValidationError } from "./InputValidator";
|
|
10
|
+
|
|
11
|
+
export interface SecurityVulnerability {
|
|
12
|
+
id: string;
|
|
13
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
14
|
+
type: string;
|
|
15
|
+
description: string;
|
|
16
|
+
location: {
|
|
17
|
+
file?: string;
|
|
18
|
+
line?: number;
|
|
19
|
+
column?: number;
|
|
20
|
+
context?: string;
|
|
21
|
+
};
|
|
22
|
+
remediation: {
|
|
23
|
+
suggested: string;
|
|
24
|
+
automated: boolean;
|
|
25
|
+
confidence: number;
|
|
26
|
+
};
|
|
27
|
+
metadata: {
|
|
28
|
+
cweId?: string;
|
|
29
|
+
cvssScore?: number;
|
|
30
|
+
exploitability: "high" | "medium" | "low";
|
|
31
|
+
detected: Date;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SecurityScanResult {
|
|
36
|
+
scanId: string;
|
|
37
|
+
timestamp: Date;
|
|
38
|
+
duration: number;
|
|
39
|
+
vulnerabilities: SecurityVulnerability[];
|
|
40
|
+
summary: {
|
|
41
|
+
total: number;
|
|
42
|
+
critical: number;
|
|
43
|
+
high: number;
|
|
44
|
+
medium: number;
|
|
45
|
+
low: number;
|
|
46
|
+
};
|
|
47
|
+
remediationAvailable: number;
|
|
48
|
+
compliance: {
|
|
49
|
+
owasp: boolean;
|
|
50
|
+
cwe: boolean;
|
|
51
|
+
gdpr: boolean;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface RemediationResult {
|
|
56
|
+
vulnerabilityId: string;
|
|
57
|
+
success: boolean;
|
|
58
|
+
action: string;
|
|
59
|
+
details: string;
|
|
60
|
+
timestamp: Date;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* AI-powered security analysis patterns
|
|
65
|
+
*/
|
|
66
|
+
const SECURITY_PATTERNS = {
|
|
67
|
+
// SQL Injection patterns
|
|
68
|
+
sqlInjection: [
|
|
69
|
+
/['"\-\-;]|\/\*|\*\//g,
|
|
70
|
+
/(union|select|insert|update|delete|drop|create|alter)\s+/gi,
|
|
71
|
+
/\b(or|and)\s+['"]?\d+['"]?\s*=\s*['"]?\d+['"]?/gi,
|
|
72
|
+
/\b(char|ascii|substring|length|concat)\s*\(/gi,
|
|
73
|
+
],
|
|
74
|
+
|
|
75
|
+
// XSS patterns
|
|
76
|
+
xss: [
|
|
77
|
+
/<script[^>]*>.*?<\/script>/gis,
|
|
78
|
+
/javascript\s*:/gi,
|
|
79
|
+
/on\w+\s*=\s*['"][^'"]*['"]?/gi,
|
|
80
|
+
/eval\s*\(/gi,
|
|
81
|
+
/expression\s*\(/gi,
|
|
82
|
+
/<iframe[^>]*>/gi,
|
|
83
|
+
],
|
|
84
|
+
|
|
85
|
+
// Path Traversal
|
|
86
|
+
pathTraversal: [/\.\.[\/\\]/g, /[\/\\]\.\.$/g, /%2e%2e/gi, /%252e%252e/gi, /\x2e\x2e/g],
|
|
87
|
+
|
|
88
|
+
// Command Injection
|
|
89
|
+
commandInjection: [/[;&|`$]/g, /\b(rm|cat|ls|ps|kill|sudo|su)\s/gi, /\$\([^)]*\)/g, /`[^`]*`/g],
|
|
90
|
+
|
|
91
|
+
// Credential Exposure
|
|
92
|
+
credentials: [
|
|
93
|
+
/password\s*[:=]\s*['"][^'"]{8,}/gi,
|
|
94
|
+
/api[_-]?key\s*[:=]\s*['"][^'"]{16,}/gi,
|
|
95
|
+
/token\s*[:=]\s*['"][^'"]{20,}/gi,
|
|
96
|
+
/secret\s*[:=]\s*['"][^'"]{16,}/gi,
|
|
97
|
+
/private[_-]?key/gi,
|
|
98
|
+
],
|
|
99
|
+
|
|
100
|
+
// LDAP Injection
|
|
101
|
+
ldapInjection: [/[()&|!]/g, /\*[^*]*\*/g, /\\\d{2}/g],
|
|
102
|
+
|
|
103
|
+
// NoSQL Injection
|
|
104
|
+
nosqlInjection: [/\$where/gi, /\$ne/gi, /\$gt/gi, /\$regex/gi, /\$exists/gi],
|
|
105
|
+
|
|
106
|
+
// CSRF vulnerabilities
|
|
107
|
+
csrf: [/GET\s+.*(?:delete|remove|update|create)/gi, /action\s*=\s*['"][^'"]*(?:delete|admin|config)/gi],
|
|
108
|
+
|
|
109
|
+
// Information Disclosure
|
|
110
|
+
infoDisclosure: [/error\s*[:=]\s*true/gi, /debug\s*[:=]\s*true/gi, /trace\s*[:=]\s*true/gi, /stack\s*trace/gi],
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* AI Security Scanner with machine learning capabilities
|
|
115
|
+
*/
|
|
116
|
+
export class AISecurityScanner {
|
|
117
|
+
private vulnerabilities: SecurityVulnerability[] = [];
|
|
118
|
+
private scanHistory: SecurityScanResult[] = [];
|
|
119
|
+
private remediationHistory: RemediationResult[] = [];
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Perform comprehensive security scan
|
|
123
|
+
*/
|
|
124
|
+
async performScan(
|
|
125
|
+
options: {
|
|
126
|
+
targets?: string[];
|
|
127
|
+
depth?: "shallow" | "deep" | "comprehensive";
|
|
128
|
+
includeFileSystem?: boolean;
|
|
129
|
+
includeRuntime?: boolean;
|
|
130
|
+
} = {},
|
|
131
|
+
): Promise<SecurityScanResult> {
|
|
132
|
+
const scanId = SecurityUtils.generateSecureToken(16);
|
|
133
|
+
const startTime = Date.now();
|
|
134
|
+
|
|
135
|
+
console.log(`[Security Scanner] Starting AI-powered security scan ${scanId}`);
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
this.vulnerabilities = [];
|
|
139
|
+
|
|
140
|
+
// Perform different types of scans
|
|
141
|
+
await this.scanCodebase(options.targets);
|
|
142
|
+
|
|
143
|
+
if (options.includeRuntime) {
|
|
144
|
+
await this.scanRuntimeEnvironment();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (options.includeFileSystem) {
|
|
148
|
+
await this.scanFileSystem();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
await this.scanConfigurations();
|
|
152
|
+
await this.scanDependencies();
|
|
153
|
+
await this.performAIAnalysis();
|
|
154
|
+
|
|
155
|
+
const duration = Date.now() - startTime;
|
|
156
|
+
const result = this.generateScanResult(scanId, duration);
|
|
157
|
+
|
|
158
|
+
this.scanHistory.push(result);
|
|
159
|
+
|
|
160
|
+
console.log(`[Security Scanner] Scan completed: ${result.summary.total} vulnerabilities found`);
|
|
161
|
+
|
|
162
|
+
return result;
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.error("[Security Scanner] Scan failed:", error);
|
|
165
|
+
throw new SecurityValidationError("Security scan failed", [{ message: String(error) }]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Scan codebase for vulnerabilities
|
|
171
|
+
*/
|
|
172
|
+
private async scanCodebase(targets?: string[]): Promise<void> {
|
|
173
|
+
const defaultTargets = ["src/", "tests/", "scripts/"];
|
|
174
|
+
const scanTargets = targets || defaultTargets;
|
|
175
|
+
|
|
176
|
+
for (const target of scanTargets) {
|
|
177
|
+
await this.scanDirectory(target);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Recursively scan directory for security issues
|
|
183
|
+
*/
|
|
184
|
+
private async scanDirectory(dirPath: string): Promise<void> {
|
|
185
|
+
try {
|
|
186
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
187
|
+
|
|
188
|
+
for (const entry of entries) {
|
|
189
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
190
|
+
|
|
191
|
+
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
192
|
+
await this.scanDirectory(fullPath);
|
|
193
|
+
} else if (entry.isFile() && this.shouldScanFile(entry.name)) {
|
|
194
|
+
await this.scanFile(fullPath);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
} catch (error) {
|
|
198
|
+
// Directory might not exist or be accessible
|
|
199
|
+
console.warn(`[Security Scanner] Cannot scan directory ${dirPath}:`, error);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Check if file should be scanned
|
|
205
|
+
*/
|
|
206
|
+
private shouldScanFile(filename: string): boolean {
|
|
207
|
+
const scanExtensions = [".ts", ".js", ".json", ".yml", ".yaml", ".env", ".config"];
|
|
208
|
+
const ext = path.extname(filename).toLowerCase();
|
|
209
|
+
return scanExtensions.includes(ext) || filename.startsWith(".");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Scan individual file for vulnerabilities
|
|
214
|
+
*/
|
|
215
|
+
private async scanFile(filePath: string): Promise<void> {
|
|
216
|
+
try {
|
|
217
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
218
|
+
const lines = content.split("\n");
|
|
219
|
+
|
|
220
|
+
// Scan for different vulnerability types
|
|
221
|
+
this.scanForSQLInjection(filePath, content, lines);
|
|
222
|
+
this.scanForXSS(filePath, content, lines);
|
|
223
|
+
this.scanForPathTraversal(filePath, content, lines);
|
|
224
|
+
this.scanForCommandInjection(filePath, content, lines);
|
|
225
|
+
this.scanForCredentialExposure(filePath, content, lines);
|
|
226
|
+
this.scanForLDAPInjection(filePath, content, lines);
|
|
227
|
+
this.scanForNoSQLInjection(filePath, content, lines);
|
|
228
|
+
this.scanForCSRF(filePath, content, lines);
|
|
229
|
+
this.scanForInfoDisclosure(filePath, content, lines);
|
|
230
|
+
this.scanForInsecureConfiguration(filePath, content, lines);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
console.warn(`[Security Scanner] Cannot scan file ${filePath}:`, error);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Scan for SQL injection vulnerabilities
|
|
238
|
+
*/
|
|
239
|
+
private scanForSQLInjection(filePath: string, content: string, lines: string[]): void {
|
|
240
|
+
SECURITY_PATTERNS.sqlInjection.forEach((pattern, index) => {
|
|
241
|
+
const matches = Array.from(content.matchAll(pattern));
|
|
242
|
+
|
|
243
|
+
matches.forEach((match) => {
|
|
244
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
245
|
+
|
|
246
|
+
this.addVulnerability({
|
|
247
|
+
id: `sql-${Date.now()}-${index}`,
|
|
248
|
+
severity: "high",
|
|
249
|
+
type: "SQL Injection",
|
|
250
|
+
description: `Potential SQL injection vulnerability detected: ${match[0]}`,
|
|
251
|
+
location: {
|
|
252
|
+
file: filePath,
|
|
253
|
+
line: lineNumber,
|
|
254
|
+
context: lines[lineNumber - 1]?.trim(),
|
|
255
|
+
},
|
|
256
|
+
remediation: {
|
|
257
|
+
suggested: "Use parameterized queries or prepared statements",
|
|
258
|
+
automated: true,
|
|
259
|
+
confidence: 0.8,
|
|
260
|
+
},
|
|
261
|
+
metadata: {
|
|
262
|
+
cweId: "CWE-89",
|
|
263
|
+
cvssScore: 8.1,
|
|
264
|
+
exploitability: "high",
|
|
265
|
+
detected: new Date(),
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Scan for XSS vulnerabilities
|
|
274
|
+
*/
|
|
275
|
+
private scanForXSS(filePath: string, content: string, lines: string[]): void {
|
|
276
|
+
SECURITY_PATTERNS.xss.forEach((pattern, index) => {
|
|
277
|
+
const matches = Array.from(content.matchAll(pattern));
|
|
278
|
+
|
|
279
|
+
matches.forEach((match) => {
|
|
280
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
281
|
+
|
|
282
|
+
this.addVulnerability({
|
|
283
|
+
id: `xss-${Date.now()}-${index}`,
|
|
284
|
+
severity: "high",
|
|
285
|
+
type: "Cross-Site Scripting (XSS)",
|
|
286
|
+
description: `Potential XSS vulnerability detected: ${match[0]}`,
|
|
287
|
+
location: {
|
|
288
|
+
file: filePath,
|
|
289
|
+
line: lineNumber,
|
|
290
|
+
context: lines[lineNumber - 1]?.trim(),
|
|
291
|
+
},
|
|
292
|
+
remediation: {
|
|
293
|
+
suggested: "Sanitize user input and encode output",
|
|
294
|
+
automated: true,
|
|
295
|
+
confidence: 0.7,
|
|
296
|
+
},
|
|
297
|
+
metadata: {
|
|
298
|
+
cweId: "CWE-79",
|
|
299
|
+
cvssScore: 7.5,
|
|
300
|
+
exploitability: "medium",
|
|
301
|
+
detected: new Date(),
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Scan for path traversal vulnerabilities
|
|
310
|
+
*/
|
|
311
|
+
private scanForPathTraversal(filePath: string, content: string, lines: string[]): void {
|
|
312
|
+
SECURITY_PATTERNS.pathTraversal.forEach((pattern, index) => {
|
|
313
|
+
const matches = Array.from(content.matchAll(pattern));
|
|
314
|
+
|
|
315
|
+
matches.forEach((match) => {
|
|
316
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
317
|
+
|
|
318
|
+
this.addVulnerability({
|
|
319
|
+
id: `path-${Date.now()}-${index}`,
|
|
320
|
+
severity: "medium",
|
|
321
|
+
type: "Path Traversal",
|
|
322
|
+
description: `Potential path traversal vulnerability detected: ${match[0]}`,
|
|
323
|
+
location: {
|
|
324
|
+
file: filePath,
|
|
325
|
+
line: lineNumber,
|
|
326
|
+
context: lines[lineNumber - 1]?.trim(),
|
|
327
|
+
},
|
|
328
|
+
remediation: {
|
|
329
|
+
suggested: "Validate and sanitize file paths",
|
|
330
|
+
automated: true,
|
|
331
|
+
confidence: 0.9,
|
|
332
|
+
},
|
|
333
|
+
metadata: {
|
|
334
|
+
cweId: "CWE-22",
|
|
335
|
+
cvssScore: 6.5,
|
|
336
|
+
exploitability: "medium",
|
|
337
|
+
detected: new Date(),
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Scan for command injection vulnerabilities
|
|
346
|
+
*/
|
|
347
|
+
private scanForCommandInjection(filePath: string, content: string, lines: string[]): void {
|
|
348
|
+
SECURITY_PATTERNS.commandInjection.forEach((pattern, index) => {
|
|
349
|
+
const matches = Array.from(content.matchAll(pattern));
|
|
350
|
+
|
|
351
|
+
matches.forEach((match) => {
|
|
352
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
353
|
+
|
|
354
|
+
this.addVulnerability({
|
|
355
|
+
id: `cmd-${Date.now()}-${index}`,
|
|
356
|
+
severity: "critical",
|
|
357
|
+
type: "Command Injection",
|
|
358
|
+
description: `Potential command injection vulnerability detected: ${match[0]}`,
|
|
359
|
+
location: {
|
|
360
|
+
file: filePath,
|
|
361
|
+
line: lineNumber,
|
|
362
|
+
context: lines[lineNumber - 1]?.trim(),
|
|
363
|
+
},
|
|
364
|
+
remediation: {
|
|
365
|
+
suggested: "Use safe APIs and validate input",
|
|
366
|
+
automated: false,
|
|
367
|
+
confidence: 0.6,
|
|
368
|
+
},
|
|
369
|
+
metadata: {
|
|
370
|
+
cweId: "CWE-78",
|
|
371
|
+
cvssScore: 9.0,
|
|
372
|
+
exploitability: "high",
|
|
373
|
+
detected: new Date(),
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Scan for credential exposure
|
|
382
|
+
*/
|
|
383
|
+
private scanForCredentialExposure(filePath: string, content: string, lines: string[]): void {
|
|
384
|
+
SECURITY_PATTERNS.credentials.forEach((pattern, index) => {
|
|
385
|
+
const matches = Array.from(content.matchAll(pattern));
|
|
386
|
+
|
|
387
|
+
matches.forEach((match) => {
|
|
388
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
389
|
+
|
|
390
|
+
this.addVulnerability({
|
|
391
|
+
id: `cred-${Date.now()}-${index}`,
|
|
392
|
+
severity: "critical",
|
|
393
|
+
type: "Credential Exposure",
|
|
394
|
+
description: `Potential hardcoded credential detected`,
|
|
395
|
+
location: {
|
|
396
|
+
file: filePath,
|
|
397
|
+
line: lineNumber,
|
|
398
|
+
context: "[REDACTED FOR SECURITY]",
|
|
399
|
+
},
|
|
400
|
+
remediation: {
|
|
401
|
+
suggested: "Move credentials to environment variables or secure vault",
|
|
402
|
+
automated: true,
|
|
403
|
+
confidence: 0.85,
|
|
404
|
+
},
|
|
405
|
+
metadata: {
|
|
406
|
+
cweId: "CWE-798",
|
|
407
|
+
cvssScore: 9.8,
|
|
408
|
+
exploitability: "high",
|
|
409
|
+
detected: new Date(),
|
|
410
|
+
},
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Scan for LDAP injection vulnerabilities
|
|
418
|
+
*/
|
|
419
|
+
private scanForLDAPInjection(filePath: string, content: string, lines: string[]): void {
|
|
420
|
+
SECURITY_PATTERNS.ldapInjection.forEach((pattern, index) => {
|
|
421
|
+
const matches = Array.from(content.matchAll(pattern));
|
|
422
|
+
|
|
423
|
+
matches.forEach((match) => {
|
|
424
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
425
|
+
|
|
426
|
+
this.addVulnerability({
|
|
427
|
+
id: `ldap-${Date.now()}-${index}`,
|
|
428
|
+
severity: "medium",
|
|
429
|
+
type: "LDAP Injection",
|
|
430
|
+
description: `Potential LDAP injection vulnerability detected: ${match[0]}`,
|
|
431
|
+
location: {
|
|
432
|
+
file: filePath,
|
|
433
|
+
line: lineNumber,
|
|
434
|
+
context: lines[lineNumber - 1]?.trim(),
|
|
435
|
+
},
|
|
436
|
+
remediation: {
|
|
437
|
+
suggested: "Escape LDAP special characters",
|
|
438
|
+
automated: true,
|
|
439
|
+
confidence: 0.7,
|
|
440
|
+
},
|
|
441
|
+
metadata: {
|
|
442
|
+
cweId: "CWE-90",
|
|
443
|
+
cvssScore: 6.8,
|
|
444
|
+
exploitability: "medium",
|
|
445
|
+
detected: new Date(),
|
|
446
|
+
},
|
|
447
|
+
});
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Scan for NoSQL injection vulnerabilities
|
|
454
|
+
*/
|
|
455
|
+
private scanForNoSQLInjection(filePath: string, content: string, lines: string[]): void {
|
|
456
|
+
SECURITY_PATTERNS.nosqlInjection.forEach((pattern, index) => {
|
|
457
|
+
const matches = Array.from(content.matchAll(pattern));
|
|
458
|
+
|
|
459
|
+
matches.forEach((match) => {
|
|
460
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
461
|
+
|
|
462
|
+
this.addVulnerability({
|
|
463
|
+
id: `nosql-${Date.now()}-${index}`,
|
|
464
|
+
severity: "high",
|
|
465
|
+
type: "NoSQL Injection",
|
|
466
|
+
description: `Potential NoSQL injection vulnerability detected: ${match[0]}`,
|
|
467
|
+
location: {
|
|
468
|
+
file: filePath,
|
|
469
|
+
line: lineNumber,
|
|
470
|
+
context: lines[lineNumber - 1]?.trim(),
|
|
471
|
+
},
|
|
472
|
+
remediation: {
|
|
473
|
+
suggested: "Validate and sanitize NoSQL queries",
|
|
474
|
+
automated: true,
|
|
475
|
+
confidence: 0.75,
|
|
476
|
+
},
|
|
477
|
+
metadata: {
|
|
478
|
+
cweId: "CWE-943",
|
|
479
|
+
cvssScore: 7.8,
|
|
480
|
+
exploitability: "medium",
|
|
481
|
+
detected: new Date(),
|
|
482
|
+
},
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Scan for CSRF vulnerabilities
|
|
490
|
+
*/
|
|
491
|
+
private scanForCSRF(filePath: string, content: string, lines: string[]): void {
|
|
492
|
+
SECURITY_PATTERNS.csrf.forEach((pattern, index) => {
|
|
493
|
+
const matches = Array.from(content.matchAll(pattern));
|
|
494
|
+
|
|
495
|
+
matches.forEach((match) => {
|
|
496
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
497
|
+
|
|
498
|
+
this.addVulnerability({
|
|
499
|
+
id: `csrf-${Date.now()}-${index}`,
|
|
500
|
+
severity: "medium",
|
|
501
|
+
type: "Cross-Site Request Forgery (CSRF)",
|
|
502
|
+
description: `Potential CSRF vulnerability detected: ${match[0]}`,
|
|
503
|
+
location: {
|
|
504
|
+
file: filePath,
|
|
505
|
+
line: lineNumber,
|
|
506
|
+
context: lines[lineNumber - 1]?.trim(),
|
|
507
|
+
},
|
|
508
|
+
remediation: {
|
|
509
|
+
suggested: "Implement CSRF tokens and verify HTTP methods",
|
|
510
|
+
automated: false,
|
|
511
|
+
confidence: 0.6,
|
|
512
|
+
},
|
|
513
|
+
metadata: {
|
|
514
|
+
cweId: "CWE-352",
|
|
515
|
+
cvssScore: 6.5,
|
|
516
|
+
exploitability: "medium",
|
|
517
|
+
detected: new Date(),
|
|
518
|
+
},
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Scan for information disclosure vulnerabilities
|
|
526
|
+
*/
|
|
527
|
+
private scanForInfoDisclosure(filePath: string, content: string, lines: string[]): void {
|
|
528
|
+
SECURITY_PATTERNS.infoDisclosure.forEach((pattern, index) => {
|
|
529
|
+
const matches = Array.from(content.matchAll(pattern));
|
|
530
|
+
|
|
531
|
+
matches.forEach((match) => {
|
|
532
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
533
|
+
|
|
534
|
+
this.addVulnerability({
|
|
535
|
+
id: `info-${Date.now()}-${index}`,
|
|
536
|
+
severity: "low",
|
|
537
|
+
type: "Information Disclosure",
|
|
538
|
+
description: `Potential information disclosure detected: ${match[0]}`,
|
|
539
|
+
location: {
|
|
540
|
+
file: filePath,
|
|
541
|
+
line: lineNumber,
|
|
542
|
+
context: lines[lineNumber - 1]?.trim(),
|
|
543
|
+
},
|
|
544
|
+
remediation: {
|
|
545
|
+
suggested: "Disable debug information in production",
|
|
546
|
+
automated: true,
|
|
547
|
+
confidence: 0.8,
|
|
548
|
+
},
|
|
549
|
+
metadata: {
|
|
550
|
+
cweId: "CWE-200",
|
|
551
|
+
cvssScore: 4.3,
|
|
552
|
+
exploitability: "low",
|
|
553
|
+
detected: new Date(),
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Scan for insecure configuration
|
|
562
|
+
*/
|
|
563
|
+
private scanForInsecureConfiguration(filePath: string, content: string, lines: string[]): void {
|
|
564
|
+
const insecurePatterns = [
|
|
565
|
+
{ pattern: /ssl\s*[:=]\s*false/gi, desc: "SSL disabled" },
|
|
566
|
+
{ pattern: /verify\s*[:=]\s*false/gi, desc: "Certificate verification disabled" },
|
|
567
|
+
{ pattern: /secure\s*[:=]\s*false/gi, desc: "Insecure configuration" },
|
|
568
|
+
{ pattern: /http:\/\//gi, desc: "HTTP instead of HTTPS" },
|
|
569
|
+
];
|
|
570
|
+
|
|
571
|
+
insecurePatterns.forEach((item, index) => {
|
|
572
|
+
const matches = Array.from(content.matchAll(item.pattern));
|
|
573
|
+
|
|
574
|
+
matches.forEach((match) => {
|
|
575
|
+
const lineNumber = this.getLineNumber(content, match.index || 0);
|
|
576
|
+
|
|
577
|
+
this.addVulnerability({
|
|
578
|
+
id: `config-${Date.now()}-${index}`,
|
|
579
|
+
severity: "medium",
|
|
580
|
+
type: "Insecure Configuration",
|
|
581
|
+
description: `${item.desc}: ${match[0]}`,
|
|
582
|
+
location: {
|
|
583
|
+
file: filePath,
|
|
584
|
+
line: lineNumber,
|
|
585
|
+
context: lines[lineNumber - 1]?.trim(),
|
|
586
|
+
},
|
|
587
|
+
remediation: {
|
|
588
|
+
suggested: "Enable secure configuration options",
|
|
589
|
+
automated: true,
|
|
590
|
+
confidence: 0.9,
|
|
591
|
+
},
|
|
592
|
+
metadata: {
|
|
593
|
+
cweId: "CWE-16",
|
|
594
|
+
cvssScore: 5.0,
|
|
595
|
+
exploitability: "medium",
|
|
596
|
+
detected: new Date(),
|
|
597
|
+
},
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Scan runtime environment for security issues
|
|
605
|
+
*/
|
|
606
|
+
private async scanRuntimeEnvironment(): Promise<void> {
|
|
607
|
+
// Check environment variables for exposed secrets
|
|
608
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
609
|
+
if (this.containsSensitiveData(key, value || "")) {
|
|
610
|
+
this.addVulnerability({
|
|
611
|
+
id: `env-${Date.now()}-${key}`,
|
|
612
|
+
severity: "high",
|
|
613
|
+
type: "Environment Variable Exposure",
|
|
614
|
+
description: `Sensitive data in environment variable: ${key}`,
|
|
615
|
+
location: {
|
|
616
|
+
context: "Runtime Environment",
|
|
617
|
+
},
|
|
618
|
+
remediation: {
|
|
619
|
+
suggested: "Use secure secret management",
|
|
620
|
+
automated: false,
|
|
621
|
+
confidence: 0.9,
|
|
622
|
+
},
|
|
623
|
+
metadata: {
|
|
624
|
+
cweId: "CWE-200",
|
|
625
|
+
cvssScore: 7.5,
|
|
626
|
+
exploitability: "medium",
|
|
627
|
+
detected: new Date(),
|
|
628
|
+
},
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Scan file system for security issues
|
|
636
|
+
*/
|
|
637
|
+
private async scanFileSystem(): Promise<void> {
|
|
638
|
+
const sensitiveFiles = [
|
|
639
|
+
".env",
|
|
640
|
+
".env.local",
|
|
641
|
+
".env.production",
|
|
642
|
+
"config.json",
|
|
643
|
+
"secrets.json",
|
|
644
|
+
"private.key",
|
|
645
|
+
"id_rsa",
|
|
646
|
+
];
|
|
647
|
+
|
|
648
|
+
for (const fileName of sensitiveFiles) {
|
|
649
|
+
try {
|
|
650
|
+
await fs.access(fileName);
|
|
651
|
+
this.addVulnerability({
|
|
652
|
+
id: `fs-${Date.now()}-${fileName}`,
|
|
653
|
+
severity: "medium",
|
|
654
|
+
type: "Sensitive File Exposure",
|
|
655
|
+
description: `Sensitive file found: ${fileName}`,
|
|
656
|
+
location: {
|
|
657
|
+
file: fileName,
|
|
658
|
+
},
|
|
659
|
+
remediation: {
|
|
660
|
+
suggested: "Ensure file permissions are restrictive and file is in .gitignore",
|
|
661
|
+
automated: true,
|
|
662
|
+
confidence: 0.8,
|
|
663
|
+
},
|
|
664
|
+
metadata: {
|
|
665
|
+
cweId: "CWE-200",
|
|
666
|
+
cvssScore: 6.0,
|
|
667
|
+
exploitability: "low",
|
|
668
|
+
detected: new Date(),
|
|
669
|
+
},
|
|
670
|
+
});
|
|
671
|
+
} catch {
|
|
672
|
+
// File doesn't exist, which is good
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Scan configurations for security issues
|
|
679
|
+
*/
|
|
680
|
+
private async scanConfigurations(): Promise<void> {
|
|
681
|
+
// This would scan various config files for insecure settings
|
|
682
|
+
console.log("[Security Scanner] Scanning configurations...");
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* Scan dependencies for known vulnerabilities
|
|
687
|
+
*/
|
|
688
|
+
private async scanDependencies(): Promise<void> {
|
|
689
|
+
// This would integrate with npm audit or similar tools
|
|
690
|
+
console.log("[Security Scanner] Scanning dependencies...");
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Perform AI-powered analysis for complex patterns
|
|
695
|
+
*/
|
|
696
|
+
private async performAIAnalysis(): Promise<void> {
|
|
697
|
+
// Advanced AI analysis would go here
|
|
698
|
+
console.log("[Security Scanner] Performing AI analysis...");
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Add vulnerability to the list
|
|
703
|
+
*/
|
|
704
|
+
private addVulnerability(vulnerability: SecurityVulnerability): void {
|
|
705
|
+
this.vulnerabilities.push(vulnerability);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Get line number from string index
|
|
710
|
+
*/
|
|
711
|
+
private getLineNumber(content: string, index: number): number {
|
|
712
|
+
return content.substring(0, index).split("\n").length;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Check if string contains sensitive data
|
|
717
|
+
*/
|
|
718
|
+
private containsSensitiveData(key: string, value: string): boolean {
|
|
719
|
+
const sensitiveKeys = ["password", "secret", "key", "token", "auth"];
|
|
720
|
+
const keyLower = key.toLowerCase();
|
|
721
|
+
|
|
722
|
+
return (
|
|
723
|
+
sensitiveKeys.some((sensitive) => keyLower.includes(sensitive)) &&
|
|
724
|
+
value.length > 8 &&
|
|
725
|
+
!/^(true|false|null|undefined|\d+)$/i.test(value)
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Generate scan result summary
|
|
731
|
+
*/
|
|
732
|
+
private generateScanResult(scanId: string, duration: number): SecurityScanResult {
|
|
733
|
+
const summary = this.vulnerabilities.reduce(
|
|
734
|
+
(acc, vuln) => {
|
|
735
|
+
acc.total++;
|
|
736
|
+
acc[vuln.severity]++;
|
|
737
|
+
return acc;
|
|
738
|
+
},
|
|
739
|
+
{ total: 0, critical: 0, high: 0, medium: 0, low: 0 },
|
|
740
|
+
);
|
|
741
|
+
|
|
742
|
+
const remediationAvailable = this.vulnerabilities.filter((v) => v.remediation.automated).length;
|
|
743
|
+
|
|
744
|
+
return {
|
|
745
|
+
scanId,
|
|
746
|
+
timestamp: new Date(),
|
|
747
|
+
duration,
|
|
748
|
+
vulnerabilities: [...this.vulnerabilities],
|
|
749
|
+
summary,
|
|
750
|
+
remediationAvailable,
|
|
751
|
+
compliance: {
|
|
752
|
+
owasp: summary.critical === 0 && summary.high < 3,
|
|
753
|
+
cwe: summary.total < 10,
|
|
754
|
+
gdpr: this.vulnerabilities.filter((v) => v.type.includes("Disclosure")).length === 0,
|
|
755
|
+
},
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Get scan history
|
|
761
|
+
*/
|
|
762
|
+
getScanHistory(): SecurityScanResult[] {
|
|
763
|
+
return [...this.scanHistory];
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Get latest scan result
|
|
768
|
+
*/
|
|
769
|
+
getLatestScan(): SecurityScanResult | null {
|
|
770
|
+
return this.scanHistory.length > 0 ? this.scanHistory[this.scanHistory.length - 1] : null;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* Clear scan history
|
|
775
|
+
*/
|
|
776
|
+
clearHistory(): void {
|
|
777
|
+
this.scanHistory = [];
|
|
778
|
+
this.remediationHistory = [];
|
|
779
|
+
}
|
|
780
|
+
}
|