mcp-wordpress 2.4.2 → 2.5.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 +114 -48
- package/dist/ajv-patch.js +34 -0
- package/dist/cache/CacheInvalidation.d.ts +3 -1
- package/dist/cache/CacheInvalidation.d.ts.map +1 -1
- package/dist/cache/CacheInvalidation.js +10 -4
- package/dist/cache/CacheInvalidation.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +3 -2
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +11 -3
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/HttpCacheWrapper.d.ts +7 -6
- package/dist/cache/HttpCacheWrapper.d.ts.map +1 -1
- package/dist/cache/HttpCacheWrapper.js +8 -5
- package/dist/cache/HttpCacheWrapper.js.map +1 -1
- package/dist/cache/__tests__/HttpCacheWrapper.test.js +6 -5
- package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -1
- package/dist/cache/index.d.ts +3 -3
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/client/CachedWordPressClient.d.ts +23 -9
- package/dist/client/CachedWordPressClient.d.ts.map +1 -1
- package/dist/client/CachedWordPressClient.js +4 -1
- package/dist/client/CachedWordPressClient.js.map +1 -1
- package/dist/client/MockWordPressClient.d.ts +2 -1
- package/dist/client/MockWordPressClient.d.ts.map +1 -1
- package/dist/client/MockWordPressClient.js +3 -1
- package/dist/client/MockWordPressClient.js.map +1 -1
- package/dist/client/api.d.ts +17 -13
- package/dist/client/api.d.ts.map +1 -1
- package/dist/client/api.js +135 -30
- package/dist/client/api.js.map +1 -1
- package/dist/client/auth.d.ts.map +1 -1
- package/dist/client/auth.js +2 -3
- package/dist/client/auth.js.map +1 -1
- package/dist/client/managers/AuthenticationManager.d.ts +55 -2
- package/dist/client/managers/AuthenticationManager.d.ts.map +1 -1
- package/dist/client/managers/AuthenticationManager.js +269 -71
- package/dist/client/managers/AuthenticationManager.js.map +1 -1
- package/dist/client/managers/BaseManager.d.ts +3 -3
- package/dist/client/managers/BaseManager.d.ts.map +1 -1
- package/dist/client/managers/BaseManager.js +11 -5
- package/dist/client/managers/BaseManager.js.map +1 -1
- package/dist/client/managers/RequestManager.d.ts +2 -2
- package/dist/client/managers/RequestManager.d.ts.map +1 -1
- package/dist/client/managers/RequestManager.js +25 -12
- package/dist/client/managers/RequestManager.js.map +1 -1
- package/dist/config/Config.d.ts +155 -0
- package/dist/config/Config.d.ts.map +1 -0
- package/dist/config/Config.js +215 -0
- package/dist/config/Config.js.map +1 -0
- package/dist/config/ConfigurationSchema.d.ts +21 -21
- package/dist/config/ConfigurationSchema.d.ts.map +1 -1
- package/dist/config/ConfigurationSchema.js +19 -2
- package/dist/config/ConfigurationSchema.js.map +1 -1
- package/dist/config/ServerConfiguration.d.ts +2 -1
- package/dist/config/ServerConfiguration.d.ts.map +1 -1
- package/dist/config/ServerConfiguration.js +50 -41
- package/dist/config/ServerConfiguration.js.map +1 -1
- package/dist/docs/DocumentationGenerator.d.ts +9 -8
- package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
- package/dist/docs/DocumentationGenerator.js +10 -7
- package/dist/docs/DocumentationGenerator.js.map +1 -1
- package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
- package/dist/docs/MarkdownFormatter.js +3 -2
- package/dist/docs/MarkdownFormatter.js.map +1 -1
- package/dist/dxt-entry.cjs +81 -0
- package/dist/dxt-entry.js +15 -14
- package/dist/dxt-entry.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -21
- package/dist/index.js.map +1 -1
- package/dist/performance/MetricsCollector.d.ts +13 -7
- package/dist/performance/MetricsCollector.d.ts.map +1 -1
- package/dist/performance/MetricsCollector.js +69 -27
- package/dist/performance/MetricsCollector.js.map +1 -1
- package/dist/performance/PerformanceAnalytics.d.ts +8 -2
- package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
- package/dist/performance/PerformanceAnalytics.js +17 -47
- package/dist/performance/PerformanceAnalytics.js.map +1 -1
- package/dist/performance/PerformanceMonitor.d.ts +2 -1
- package/dist/performance/PerformanceMonitor.d.ts.map +1 -1
- package/dist/performance/PerformanceMonitor.js +12 -13
- package/dist/performance/PerformanceMonitor.js.map +1 -1
- package/dist/performance/index.d.ts +2 -2
- package/dist/performance/index.d.ts.map +1 -1
- package/dist/security/AISecurityScanner.d.ts +1 -0
- package/dist/security/AISecurityScanner.d.ts.map +1 -1
- package/dist/security/AISecurityScanner.js +22 -12
- package/dist/security/AISecurityScanner.js.map +1 -1
- package/dist/security/AutomatedRemediation.d.ts +4 -3
- package/dist/security/AutomatedRemediation.d.ts.map +1 -1
- package/dist/security/AutomatedRemediation.js +46 -15
- package/dist/security/AutomatedRemediation.js.map +1 -1
- package/dist/security/InputValidator.d.ts +13 -9
- package/dist/security/InputValidator.d.ts.map +1 -1
- package/dist/security/InputValidator.js +4 -2
- package/dist/security/InputValidator.js.map +1 -1
- package/dist/security/SecurityCIPipeline.d.ts +1 -1
- package/dist/security/SecurityCIPipeline.d.ts.map +1 -1
- package/dist/security/SecurityCIPipeline.js +38 -29
- package/dist/security/SecurityCIPipeline.js.map +1 -1
- package/dist/security/SecurityConfig.d.ts +3 -3
- package/dist/security/SecurityConfig.d.ts.map +1 -1
- package/dist/security/SecurityConfig.js +13 -9
- package/dist/security/SecurityConfig.js.map +1 -1
- package/dist/security/SecurityConfigManager.d.ts +2 -2
- package/dist/security/SecurityConfigManager.d.ts.map +1 -1
- package/dist/security/SecurityConfigManager.js +20 -15
- package/dist/security/SecurityConfigManager.js.map +1 -1
- package/dist/security/SecurityMonitoring.d.ts +2 -2
- package/dist/security/SecurityMonitoring.d.ts.map +1 -1
- package/dist/security/SecurityMonitoring.js +19 -17
- package/dist/security/SecurityMonitoring.js.map +1 -1
- package/dist/security/SecurityReviewer.d.ts.map +1 -1
- package/dist/security/SecurityReviewer.js +10 -7
- package/dist/security/SecurityReviewer.js.map +1 -1
- package/dist/security/index.d.ts +24 -23
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +52 -23
- package/dist/security/index.js.map +1 -1
- package/dist/server/ConnectionTester.d.ts +12 -4
- package/dist/server/ConnectionTester.d.ts.map +1 -1
- package/dist/server/ConnectionTester.js +96 -22
- package/dist/server/ConnectionTester.js.map +1 -1
- package/dist/server/ToolRegistry.d.ts +2 -2
- package/dist/server/ToolRegistry.d.ts.map +1 -1
- package/dist/server/ToolRegistry.js +10 -5
- package/dist/server/ToolRegistry.js.map +1 -1
- package/dist/tools/BaseToolManager.d.ts +47 -11
- package/dist/tools/BaseToolManager.d.ts.map +1 -1
- package/dist/tools/BaseToolManager.js +168 -29
- package/dist/tools/BaseToolManager.js.map +1 -1
- package/dist/tools/auth.d.ts +16 -10
- package/dist/tools/auth.d.ts.map +1 -1
- package/dist/tools/auth.js +3 -2
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/cache.d.ts +30 -30
- package/dist/tools/cache.d.ts.map +1 -1
- package/dist/tools/cache.js +1 -6
- package/dist/tools/cache.js.map +1 -1
- package/dist/tools/comments.d.ts +20 -20
- package/dist/tools/comments.d.ts.map +1 -1
- package/dist/tools/comments.js +16 -9
- package/dist/tools/comments.js.map +1 -1
- package/dist/tools/media.d.ts +18 -16
- package/dist/tools/media.d.ts.map +1 -1
- package/dist/tools/media.js +16 -15
- package/dist/tools/media.js.map +1 -1
- package/dist/tools/pages.d.ts +19 -17
- package/dist/tools/pages.d.ts.map +1 -1
- package/dist/tools/pages.js +16 -12
- package/dist/tools/pages.js.map +1 -1
- package/dist/tools/performance.d.ts +11 -1
- package/dist/tools/performance.d.ts.map +1 -1
- package/dist/tools/performance.js +67 -34
- package/dist/tools/performance.js.map +1 -1
- package/dist/tools/posts/PostHandlers.d.ts +46 -0
- package/dist/tools/posts/PostHandlers.d.ts.map +1 -0
- package/dist/tools/posts/PostHandlers.js +400 -0
- package/dist/tools/posts/PostHandlers.js.map +1 -0
- package/dist/tools/posts/PostToolDefinitions.d.ts +37 -0
- package/dist/tools/posts/PostToolDefinitions.d.ts.map +1 -0
- package/dist/tools/posts/PostToolDefinitions.js +236 -0
- package/dist/tools/posts/PostToolDefinitions.js.map +1 -0
- package/dist/tools/posts/index.d.ts +138 -0
- package/dist/tools/posts/index.d.ts.map +1 -0
- package/dist/tools/posts/index.js +163 -0
- package/dist/tools/posts/index.js.map +1 -0
- package/dist/tools/posts.d.ts +10 -246
- package/dist/tools/posts.d.ts.map +1 -1
- package/dist/tools/posts.js +11 -723
- package/dist/tools/posts.js.map +1 -1
- package/dist/tools/site.d.ts +19 -18
- package/dist/tools/site.d.ts.map +1 -1
- package/dist/tools/site.js +14 -10
- package/dist/tools/site.js.map +1 -1
- package/dist/tools/taxonomies.d.ts +23 -24
- package/dist/tools/taxonomies.d.ts.map +1 -1
- package/dist/tools/taxonomies.js +24 -18
- package/dist/tools/taxonomies.js.map +1 -1
- package/dist/tools/users.d.ts +20 -15
- package/dist/tools/users.d.ts.map +1 -1
- package/dist/tools/users.js +12 -8
- package/dist/tools/users.js.map +1 -1
- package/dist/types/client.d.ts +48 -41
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/client.js +30 -5
- package/dist/types/client.js.map +1 -1
- package/dist/types/enhanced.d.ts +237 -0
- package/dist/types/enhanced.d.ts.map +1 -0
- package/dist/types/enhanced.js +49 -0
- package/dist/types/enhanced.js.map +1 -0
- package/dist/types/index.d.ts +15 -12
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/mcp.d.ts +12 -12
- package/dist/types/mcp.d.ts.map +1 -1
- package/dist/types/requests.d.ts +322 -0
- package/dist/types/requests.d.ts.map +1 -0
- package/dist/types/requests.js +8 -0
- package/dist/types/requests.js.map +1 -0
- package/dist/types/tools.d.ts +506 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +8 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/types/wordpress.d.ts +43 -15
- package/dist/types/wordpress.d.ts.map +1 -1
- package/dist/types/wordpress.js +8 -1
- package/dist/types/wordpress.js.map +1 -1
- package/dist/utils/debug.d.ts +19 -11
- package/dist/utils/debug.d.ts.map +1 -1
- package/dist/utils/debug.js +46 -10
- package/dist/utils/debug.js.map +1 -1
- package/dist/utils/enhancedError.d.ts +8 -8
- package/dist/utils/enhancedError.d.ts.map +1 -1
- package/dist/utils/enhancedError.js.map +1 -1
- package/dist/utils/error.d.ts +2 -4
- package/dist/utils/error.d.ts.map +1 -1
- package/dist/utils/error.js +42 -5
- package/dist/utils/error.js.map +1 -1
- package/dist/utils/logger.d.ts +106 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +280 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/streaming.d.ts +9 -9
- package/dist/utils/streaming.d.ts.map +1 -1
- package/dist/utils/streaming.js +71 -52
- package/dist/utils/streaming.js.map +1 -1
- package/dist/utils/toolWrapper.d.ts +9 -7
- package/dist/utils/toolWrapper.d.ts.map +1 -1
- package/dist/utils/toolWrapper.js.map +1 -1
- package/dist/utils/validation/core.d.ts +21 -0
- package/dist/utils/validation/core.d.ts.map +1 -0
- package/dist/utils/validation/core.js +71 -0
- package/dist/utils/validation/core.js.map +1 -0
- package/dist/utils/validation/index.d.ts +25 -0
- package/dist/utils/validation/index.d.ts.map +1 -0
- package/dist/utils/validation/index.js +29 -0
- package/dist/utils/validation/index.js.map +1 -0
- package/dist/utils/validation/network.d.ts +19 -0
- package/dist/utils/validation/network.d.ts.map +1 -0
- package/dist/utils/validation/network.js +93 -0
- package/dist/utils/validation/network.js.map +1 -0
- package/dist/utils/validation/rateLimit.d.ts +21 -0
- package/dist/utils/validation/rateLimit.d.ts.map +1 -0
- package/dist/utils/validation/rateLimit.js +43 -0
- package/dist/utils/validation/rateLimit.js.map +1 -0
- package/dist/utils/validation/security.d.ts +29 -0
- package/dist/utils/validation/security.d.ts.map +1 -0
- package/dist/utils/validation/security.js +327 -0
- package/dist/utils/validation/security.js.map +1 -0
- package/dist/utils/validation/wordpress.d.ts +31 -0
- package/dist/utils/validation/wordpress.d.ts.map +1 -0
- package/dist/utils/validation/wordpress.js +146 -0
- package/dist/utils/validation/wordpress.js.map +1 -0
- package/dist/utils/validation.d.ts +13 -82
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +25 -343
- package/dist/utils/validation.js.map +1 -1
- package/docs/BADGE_UPDATES.md +132 -0
- package/docs/CI_CD_IMPROVEMENTS.md +191 -0
- package/docs/INCREMENTAL_COVERAGE.md +183 -0
- package/docs/api/README.md +3 -1
- package/docs/api/openapi.json +5 -1
- package/docs/api/summary.json +1 -1
- package/docs/api/tools/wp_create_post.md +12 -14
- package/docs/examples/claude-desktop-config.md +1 -1
- package/docs/examples/docker-production.md +100 -93
- package/docs/examples/multi-site-setup.md +5 -4
- package/docs/examples/single-site-setup.md +3 -4
- package/docs/examples/use-case-workflows.md +4 -5
- package/docs/integrations/claude-desktop.md +31 -31
- package/docs/integrations/cline.md +4 -4
- package/docs/integrations/vs-code.md +9 -8
- package/docs/user-guides/SMITHERY_SETUP.md +10 -10
- package/package.json +44 -25
- package/src/cache/CacheInvalidation.ts +12 -5
- package/src/cache/CacheManager.ts +18 -15
- package/src/cache/HttpCacheWrapper.ts +30 -59
- package/src/cache/__tests__/HttpCacheWrapper.test.ts +6 -5
- package/src/cache/index.ts +3 -14
- package/src/client/CachedWordPressClient.ts +32 -30
- package/src/client/MockWordPressClient.ts +4 -2
- package/src/client/api.ts +186 -64
- package/src/client/auth.ts +15 -40
- package/src/client/managers/AuthenticationManager.ts +337 -77
- package/src/client/managers/BaseManager.ts +18 -30
- package/src/client/managers/RequestManager.ts +39 -44
- package/src/config/Config.ts +308 -0
- package/src/config/ConfigurationSchema.ts +23 -2
- package/src/config/ServerConfiguration.ts +51 -47
- package/src/docs/DocumentationGenerator.ts +50 -39
- package/src/docs/MarkdownFormatter.ts +19 -29
- package/src/dxt-entry.cjs +26 -16
- package/src/dxt-entry.ts +17 -27
- package/src/index.ts +42 -28
- package/src/performance/MetricsCollector.ts +108 -86
- package/src/performance/PerformanceAnalytics.ts +69 -164
- package/src/performance/PerformanceMonitor.ts +32 -47
- package/src/performance/index.ts +2 -10
- package/src/security/AISecurityScanner.ts +22 -12
- package/src/security/AutomatedRemediation.ts +49 -18
- package/src/security/InputValidator.ts +9 -6
- package/src/security/SecurityCIPipeline.ts +53 -37
- package/src/security/SecurityConfig.ts +22 -22
- package/src/security/SecurityConfigManager.ts +23 -19
- package/src/security/SecurityMonitoring.ts +24 -21
- package/src/security/SecurityReviewer.ts +10 -7
- package/src/security/index.ts +64 -29
- package/src/server/ConnectionTester.ts +120 -31
- package/src/server/ToolRegistry.ts +31 -21
- package/src/tools/BaseToolManager.ts +286 -33
- package/src/tools/auth.ts +20 -8
- package/src/tools/cache.ts +5 -15
- package/src/tools/comments.ts +34 -48
- package/src/tools/media.ts +41 -53
- package/src/tools/pages.ts +32 -54
- package/src/tools/performance.ts +141 -176
- package/src/tools/posts/PostHandlers.ts +474 -0
- package/src/tools/posts/PostToolDefinitions.ts +250 -0
- package/src/tools/posts/index.ts +192 -0
- package/src/tools/posts.ts +24 -780
- package/src/tools/site.ts +34 -19
- package/src/tools/taxonomies.ts +41 -57
- package/src/tools/users.ts +28 -16
- package/src/types/client.ts +114 -138
- package/src/types/enhanced.ts +318 -0
- package/src/types/index.ts +51 -30
- package/src/types/mcp.ts +20 -42
- package/src/types/requests.ts +378 -0
- package/src/types/tools.ts +608 -0
- package/src/types/wordpress.ts +56 -34
- package/src/utils/debug.ts +77 -59
- package/src/utils/enhancedError.ts +8 -8
- package/src/utils/error.ts +53 -31
- package/src/utils/logger.ts +351 -0
- package/src/utils/streaming.ts +86 -68
- package/src/utils/toolWrapper.ts +10 -12
- package/src/utils/validation/core.ts +108 -0
- package/src/utils/validation/index.ts +36 -0
- package/src/utils/validation/network.ts +132 -0
- package/src/utils/validation/rateLimit.ts +54 -0
- package/src/utils/validation/security.ts +361 -0
- package/src/utils/validation/wordpress.ts +180 -0
- package/src/utils/validation.ts +47 -470
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import * as fs from "fs/promises";
|
|
7
7
|
import * as path from "path";
|
|
8
|
-
import { SecurityUtils } from "./SecurityConfig";
|
|
9
|
-
import { SecurityValidationError } from "./InputValidator";
|
|
8
|
+
import { SecurityUtils } from "./SecurityConfig.js";
|
|
9
|
+
import { SecurityValidationError } from "./InputValidator.js";
|
|
10
|
+
import { LoggerFactory } from "../utils/logger.js";
|
|
10
11
|
|
|
11
12
|
export interface SecurityVulnerability {
|
|
12
13
|
id: string;
|
|
@@ -66,7 +67,7 @@ export interface RemediationResult {
|
|
|
66
67
|
const SECURITY_PATTERNS = {
|
|
67
68
|
// SQL Injection patterns
|
|
68
69
|
sqlInjection: [
|
|
69
|
-
/['"\-\-;]|\/\*|\*\//g,
|
|
70
|
+
/['"\-\-;]|\/\*|\*\//g, // Match quotes, double hyphens, semicolons, and SQL comments
|
|
70
71
|
/(union|select|insert|update|delete|drop|create|alter)\s+/gi,
|
|
71
72
|
/\b(or|and)\s+['"]?\d+['"]?\s*=\s*['"]?\d+['"]?/gi,
|
|
72
73
|
/\b(char|ascii|substring|length|concat)\s*\(/gi,
|
|
@@ -74,7 +75,7 @@ const SECURITY_PATTERNS = {
|
|
|
74
75
|
|
|
75
76
|
// XSS patterns
|
|
76
77
|
xss: [
|
|
77
|
-
/<script[^>]*>.*?<\/script>/gis,
|
|
78
|
+
/<script[^>]*>.*?<\/script>/gis, // Match script tags with any attributes
|
|
78
79
|
/javascript\s*:/gi,
|
|
79
80
|
/on\w+\s*=\s*['"][^'"]*['"]?/gi,
|
|
80
81
|
/eval\s*\(/gi,
|
|
@@ -114,6 +115,7 @@ const SECURITY_PATTERNS = {
|
|
|
114
115
|
* AI Security Scanner with machine learning capabilities
|
|
115
116
|
*/
|
|
116
117
|
export class AISecurityScanner {
|
|
118
|
+
private readonly logger = LoggerFactory.security();
|
|
117
119
|
private vulnerabilities: SecurityVulnerability[] = [];
|
|
118
120
|
private scanHistory: SecurityScanResult[] = [];
|
|
119
121
|
private remediationHistory: RemediationResult[] = [];
|
|
@@ -132,7 +134,7 @@ export class AISecurityScanner {
|
|
|
132
134
|
const scanId = SecurityUtils.generateSecureToken(16);
|
|
133
135
|
const startTime = Date.now();
|
|
134
136
|
|
|
135
|
-
|
|
137
|
+
this.logger.info("Starting AI-powered security scan", { scanId });
|
|
136
138
|
|
|
137
139
|
try {
|
|
138
140
|
this.vulnerabilities = [];
|
|
@@ -157,11 +159,19 @@ export class AISecurityScanner {
|
|
|
157
159
|
|
|
158
160
|
this.scanHistory.push(result);
|
|
159
161
|
|
|
160
|
-
|
|
162
|
+
this.logger.info("Security scan completed", {
|
|
163
|
+
scanId,
|
|
164
|
+
vulnerabilities: result.summary.total,
|
|
165
|
+
duration,
|
|
166
|
+
critical: result.summary.critical,
|
|
167
|
+
high: result.summary.high,
|
|
168
|
+
medium: result.summary.medium,
|
|
169
|
+
low: result.summary.low,
|
|
170
|
+
});
|
|
161
171
|
|
|
162
172
|
return result;
|
|
163
173
|
} catch (error) {
|
|
164
|
-
|
|
174
|
+
this.logger.error("Security scan failed", { scanId, error: String(error) });
|
|
165
175
|
throw new SecurityValidationError("Security scan failed", [{ message: String(error) }]);
|
|
166
176
|
}
|
|
167
177
|
}
|
|
@@ -196,7 +206,7 @@ export class AISecurityScanner {
|
|
|
196
206
|
}
|
|
197
207
|
} catch (error) {
|
|
198
208
|
// Directory might not exist or be accessible
|
|
199
|
-
|
|
209
|
+
this.logger.warn("Cannot scan directory", { dirPath, error: String(error) });
|
|
200
210
|
}
|
|
201
211
|
}
|
|
202
212
|
|
|
@@ -229,7 +239,7 @@ export class AISecurityScanner {
|
|
|
229
239
|
this.scanForInfoDisclosure(filePath, content, lines);
|
|
230
240
|
this.scanForInsecureConfiguration(filePath, content, lines);
|
|
231
241
|
} catch (error) {
|
|
232
|
-
|
|
242
|
+
this.logger.warn("Cannot scan file", { filePath, error: String(error) });
|
|
233
243
|
}
|
|
234
244
|
}
|
|
235
245
|
|
|
@@ -679,7 +689,7 @@ export class AISecurityScanner {
|
|
|
679
689
|
*/
|
|
680
690
|
private async scanConfigurations(): Promise<void> {
|
|
681
691
|
// This would scan various config files for insecure settings
|
|
682
|
-
|
|
692
|
+
this.logger.debug("Scanning configurations for security issues");
|
|
683
693
|
}
|
|
684
694
|
|
|
685
695
|
/**
|
|
@@ -687,7 +697,7 @@ export class AISecurityScanner {
|
|
|
687
697
|
*/
|
|
688
698
|
private async scanDependencies(): Promise<void> {
|
|
689
699
|
// This would integrate with npm audit or similar tools
|
|
690
|
-
|
|
700
|
+
this.logger.debug("Scanning dependencies for vulnerabilities");
|
|
691
701
|
}
|
|
692
702
|
|
|
693
703
|
/**
|
|
@@ -695,7 +705,7 @@ export class AISecurityScanner {
|
|
|
695
705
|
*/
|
|
696
706
|
private async performAIAnalysis(): Promise<void> {
|
|
697
707
|
// Advanced AI analysis would go here
|
|
698
|
-
|
|
708
|
+
this.logger.debug("Performing AI-powered security analysis");
|
|
699
709
|
}
|
|
700
710
|
|
|
701
711
|
/**
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import * as fs from "fs/promises";
|
|
7
7
|
import * as path from "path";
|
|
8
|
-
import { SecurityVulnerability, SecurityScanResult } from "./AISecurityScanner";
|
|
9
|
-
import { SecurityUtils } from "./SecurityConfig";
|
|
10
|
-
import { SecurityValidationError } from "./InputValidator";
|
|
8
|
+
import { SecurityVulnerability, SecurityScanResult } from "./AISecurityScanner.js";
|
|
9
|
+
import { SecurityUtils } from "./SecurityConfig.js";
|
|
10
|
+
import { SecurityValidationError } from "./InputValidator.js";
|
|
11
|
+
import { LoggerFactory } from "../utils/logger.js";
|
|
11
12
|
|
|
12
13
|
interface RemediationAction {
|
|
13
14
|
id: string;
|
|
@@ -20,7 +21,7 @@ interface RemediationAction {
|
|
|
20
21
|
};
|
|
21
22
|
replacement: {
|
|
22
23
|
content?: string;
|
|
23
|
-
config?: Record<string,
|
|
24
|
+
config?: Record<string, unknown>;
|
|
24
25
|
action?: string;
|
|
25
26
|
};
|
|
26
27
|
backup: {
|
|
@@ -29,7 +30,7 @@ interface RemediationAction {
|
|
|
29
30
|
};
|
|
30
31
|
validation: {
|
|
31
32
|
test?: string;
|
|
32
|
-
expected?:
|
|
33
|
+
expected?: unknown;
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -97,6 +98,7 @@ const REMEDIATION_PATTERNS = {
|
|
|
97
98
|
* Automated Security Remediation Engine
|
|
98
99
|
*/
|
|
99
100
|
export class AutomatedRemediation {
|
|
101
|
+
private readonly logger = LoggerFactory.security();
|
|
100
102
|
private remediationHistory: RemediationResult[] = [];
|
|
101
103
|
private backupDirectory = "security-backups";
|
|
102
104
|
|
|
@@ -107,7 +109,11 @@ export class AutomatedRemediation {
|
|
|
107
109
|
const planId = SecurityUtils.generateSecureToken(16);
|
|
108
110
|
const remediableVulns = scanResult.vulnerabilities.filter((v) => v.remediation.automated);
|
|
109
111
|
|
|
110
|
-
|
|
112
|
+
this.logger.info("Creating remediation plan", {
|
|
113
|
+
planId,
|
|
114
|
+
remediableVulnerabilities: remediableVulns.length,
|
|
115
|
+
totalVulnerabilities: scanResult.vulnerabilities.length,
|
|
116
|
+
});
|
|
111
117
|
|
|
112
118
|
const actions: RemediationAction[] = [];
|
|
113
119
|
let estimatedDuration = 0;
|
|
@@ -338,10 +344,14 @@ export class AutomatedRemediation {
|
|
|
338
344
|
requireConfirmation?: boolean;
|
|
339
345
|
} = {},
|
|
340
346
|
): Promise<RemediationResult[]> {
|
|
341
|
-
|
|
347
|
+
this.logger.info("Executing remediation plan", {
|
|
348
|
+
planId: plan.planId,
|
|
349
|
+
actionCount: plan.actions.length,
|
|
350
|
+
dryRun: options.dryRun,
|
|
351
|
+
});
|
|
342
352
|
|
|
343
353
|
if (options.dryRun) {
|
|
344
|
-
|
|
354
|
+
this.logger.info("Running in dry-run mode - no changes will be made");
|
|
345
355
|
return this.simulateRemediationActions(plan.actions);
|
|
346
356
|
}
|
|
347
357
|
|
|
@@ -352,16 +362,26 @@ export class AutomatedRemediation {
|
|
|
352
362
|
|
|
353
363
|
for (const action of plan.actions) {
|
|
354
364
|
try {
|
|
355
|
-
|
|
365
|
+
this.logger.debug("Executing remediation action", {
|
|
366
|
+
actionId: action.id,
|
|
367
|
+
actionType: action.type,
|
|
368
|
+
targetFile: action.target.file,
|
|
369
|
+
});
|
|
356
370
|
|
|
357
371
|
const result = await this.executeRemediationAction(action);
|
|
358
372
|
results.push(result);
|
|
359
373
|
|
|
360
374
|
if (!result.success) {
|
|
361
|
-
|
|
375
|
+
this.logger.error("Remediation action failed", {
|
|
376
|
+
actionId: action.id,
|
|
377
|
+
details: result.details,
|
|
378
|
+
});
|
|
362
379
|
}
|
|
363
380
|
} catch (error) {
|
|
364
|
-
|
|
381
|
+
this.logger.error("Remediation action threw error", {
|
|
382
|
+
actionId: action.id,
|
|
383
|
+
error: String(error),
|
|
384
|
+
});
|
|
365
385
|
results.push({
|
|
366
386
|
vulnerabilityId: action.id,
|
|
367
387
|
success: false,
|
|
@@ -375,7 +395,12 @@ export class AutomatedRemediation {
|
|
|
375
395
|
this.remediationHistory.push(...results);
|
|
376
396
|
|
|
377
397
|
const successCount = results.filter((r) => r.success).length;
|
|
378
|
-
|
|
398
|
+
this.logger.info("Remediation plan completed", {
|
|
399
|
+
planId: plan.planId,
|
|
400
|
+
successCount,
|
|
401
|
+
totalActions: results.length,
|
|
402
|
+
successRate: `${Math.round((successCount / results.length) * 100)}%`,
|
|
403
|
+
});
|
|
379
404
|
|
|
380
405
|
return results;
|
|
381
406
|
}
|
|
@@ -561,7 +586,7 @@ export class AutomatedRemediation {
|
|
|
561
586
|
const content = await fs.readFile(filePath, "utf-8");
|
|
562
587
|
await fs.writeFile(backupPath, content, "utf-8");
|
|
563
588
|
|
|
564
|
-
|
|
589
|
+
this.logger.debug("Created backup file", { backupPath });
|
|
565
590
|
return backupPath;
|
|
566
591
|
}
|
|
567
592
|
|
|
@@ -573,7 +598,7 @@ export class AutomatedRemediation {
|
|
|
573
598
|
await fs.access(this.backupDirectory);
|
|
574
599
|
} catch {
|
|
575
600
|
await fs.mkdir(this.backupDirectory, { recursive: true });
|
|
576
|
-
|
|
601
|
+
this.logger.info("Created backup directory", { directory: this.backupDirectory });
|
|
577
602
|
}
|
|
578
603
|
}
|
|
579
604
|
|
|
@@ -597,7 +622,10 @@ export class AutomatedRemediation {
|
|
|
597
622
|
|
|
598
623
|
return true;
|
|
599
624
|
} catch (error) {
|
|
600
|
-
|
|
625
|
+
this.logger.warn("Validation failed for action", {
|
|
626
|
+
actionId: action.id,
|
|
627
|
+
error: String(error),
|
|
628
|
+
});
|
|
601
629
|
return false;
|
|
602
630
|
}
|
|
603
631
|
}
|
|
@@ -635,7 +663,10 @@ export class AutomatedRemediation {
|
|
|
635
663
|
try {
|
|
636
664
|
const backupContent = await fs.readFile(backupPath, "utf-8");
|
|
637
665
|
await fs.writeFile(targetFile, backupContent, "utf-8");
|
|
638
|
-
|
|
666
|
+
this.logger.info("Rolled back file from backup", {
|
|
667
|
+
targetFile,
|
|
668
|
+
backupPath,
|
|
669
|
+
});
|
|
639
670
|
} catch (error) {
|
|
640
671
|
throw new SecurityValidationError(`Rollback failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
641
672
|
}
|
|
@@ -655,11 +686,11 @@ export class AutomatedRemediation {
|
|
|
655
686
|
|
|
656
687
|
if (now - stats.mtime.getTime() > maxAge) {
|
|
657
688
|
await fs.unlink(filePath);
|
|
658
|
-
|
|
689
|
+
this.logger.debug("Cleaned up old backup", { file });
|
|
659
690
|
}
|
|
660
691
|
}
|
|
661
692
|
} catch (error) {
|
|
662
|
-
|
|
693
|
+
this.logger.warn("Backup cleanup failed", { error: String(error) });
|
|
663
694
|
}
|
|
664
695
|
}
|
|
665
696
|
}
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
import { LoggerFactory } from "../utils/logger.js";
|
|
8
|
+
|
|
9
|
+
const logger = LoggerFactory.security();
|
|
7
10
|
|
|
8
11
|
// Common validation patterns
|
|
9
12
|
const URL_PATTERN = /^https?:\/\/[^\s<>'"{}|\\^`\[\]]+$/;
|
|
@@ -159,17 +162,17 @@ export class InputSanitizer {
|
|
|
159
162
|
* Security validation decorator for tool methods
|
|
160
163
|
*/
|
|
161
164
|
export function validateSecurity(schema: z.ZodSchema) {
|
|
162
|
-
return function (target:
|
|
165
|
+
return function (target: unknown, propertyName: string, descriptor: PropertyDescriptor) {
|
|
163
166
|
const method = descriptor.value;
|
|
164
167
|
|
|
165
|
-
descriptor.value = async function (...args:
|
|
168
|
+
descriptor.value = async function (...args: unknown[]) {
|
|
166
169
|
try {
|
|
167
170
|
// Validate input parameters
|
|
168
171
|
const params = args[0] || {};
|
|
169
172
|
const validatedParams = schema.parse(params);
|
|
170
173
|
|
|
171
174
|
// Log security validation (without sensitive data)
|
|
172
|
-
|
|
175
|
+
logger.info(`Security validation passed for ${propertyName}`, {
|
|
173
176
|
timestamp: new Date().toISOString(),
|
|
174
177
|
method: propertyName,
|
|
175
178
|
paramCount: Object.keys(validatedParams).length,
|
|
@@ -179,7 +182,7 @@ export function validateSecurity(schema: z.ZodSchema) {
|
|
|
179
182
|
return await method.call(this, validatedParams, ...args.slice(1));
|
|
180
183
|
} catch (error) {
|
|
181
184
|
// Log security validation failure
|
|
182
|
-
|
|
185
|
+
logger.error(`Security validation failed for ${propertyName}`, {
|
|
183
186
|
timestamp: new Date().toISOString(),
|
|
184
187
|
method: propertyName,
|
|
185
188
|
error: error instanceof z.ZodError ? error.errors : error instanceof Error ? error.message : String(error),
|
|
@@ -206,9 +209,9 @@ export function validateSecurity(schema: z.ZodSchema) {
|
|
|
206
209
|
* Custom security validation error
|
|
207
210
|
*/
|
|
208
211
|
export class SecurityValidationError extends Error {
|
|
209
|
-
public readonly errors:
|
|
212
|
+
public readonly errors: Array<z.ZodIssue | { message: string }>;
|
|
210
213
|
|
|
211
|
-
constructor(message: string, errors:
|
|
214
|
+
constructor(message: string, errors: Array<z.ZodIssue | { message: string }> = []) {
|
|
212
215
|
super(message);
|
|
213
216
|
this.name = "SecurityValidationError";
|
|
214
217
|
this.errors = errors;
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
* Provides security checks and gates for continuous integration and deployment
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { AISecurityScanner } from "./AISecurityScanner";
|
|
7
|
-
import { AutomatedRemediation } from "./AutomatedRemediation";
|
|
8
|
-
import { SecurityReviewer } from "./SecurityReviewer";
|
|
9
|
-
import { SecurityConfigManager } from "./SecurityConfigManager";
|
|
10
|
-
import { SecurityUtils } from "./SecurityConfig";
|
|
11
|
-
import { SecurityValidationError } from "./InputValidator";
|
|
6
|
+
import { AISecurityScanner } from "./AISecurityScanner.js";
|
|
7
|
+
import { AutomatedRemediation } from "./AutomatedRemediation.js";
|
|
8
|
+
import { SecurityReviewer } from "./SecurityReviewer.js";
|
|
9
|
+
import { SecurityConfigManager } from "./SecurityConfigManager.js";
|
|
10
|
+
import { SecurityUtils } from "./SecurityConfig.js";
|
|
11
|
+
import { SecurityValidationError } from "./InputValidator.js";
|
|
12
|
+
import { LoggerFactory } from "../utils/logger.js";
|
|
13
|
+
|
|
14
|
+
const logger = LoggerFactory.security();
|
|
12
15
|
|
|
13
16
|
interface SecurityGate {
|
|
14
17
|
id: string;
|
|
@@ -33,7 +36,7 @@ interface SecurityCheck {
|
|
|
33
36
|
enabled: boolean;
|
|
34
37
|
timeout: number;
|
|
35
38
|
retries: number;
|
|
36
|
-
parameters: Record<string,
|
|
39
|
+
parameters: Record<string, unknown>;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
export interface PipelineSecurityReport {
|
|
@@ -126,9 +129,9 @@ export class SecurityCIPipeline {
|
|
|
126
129
|
* Initialize the security pipeline
|
|
127
130
|
*/
|
|
128
131
|
async initialize(): Promise<void> {
|
|
129
|
-
|
|
132
|
+
logger.info("Initializing security CI/CD pipeline");
|
|
130
133
|
await this.configManager.initialize();
|
|
131
|
-
|
|
134
|
+
logger.info("Security pipeline ready");
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
/**
|
|
@@ -146,12 +149,16 @@ export class SecurityCIPipeline {
|
|
|
146
149
|
const reportId = SecurityUtils.generateSecureToken(16);
|
|
147
150
|
const startTime = Date.now();
|
|
148
151
|
|
|
149
|
-
|
|
152
|
+
logger.info(`Executing ${stage} security gates`, {
|
|
153
|
+
stage,
|
|
154
|
+
branch: context.branch,
|
|
155
|
+
commit: context.commit
|
|
156
|
+
});
|
|
150
157
|
|
|
151
158
|
const applicableGates = Array.from(this.gates.values()).filter((gate) => gate.stage === stage && gate.enabled);
|
|
152
159
|
|
|
153
160
|
if (applicableGates.length === 0) {
|
|
154
|
-
|
|
161
|
+
logger.warn(`No security gates configured for stage: ${stage}`, { stage });
|
|
155
162
|
return this.createEmptyReport(reportId, stage, startTime);
|
|
156
163
|
}
|
|
157
164
|
|
|
@@ -159,7 +166,7 @@ export class SecurityCIPipeline {
|
|
|
159
166
|
let overallStatus: "passed" | "failed" | "warning" = "passed";
|
|
160
167
|
|
|
161
168
|
for (const gate of applicableGates) {
|
|
162
|
-
|
|
169
|
+
logger.info(`Executing gate: ${gate.name}`, { gateName: gate.name });
|
|
163
170
|
|
|
164
171
|
try {
|
|
165
172
|
const gateResult = await this.executeSecurityGate(gate, context, options);
|
|
@@ -174,11 +181,11 @@ export class SecurityCIPipeline {
|
|
|
174
181
|
|
|
175
182
|
// Stop on blocking failure unless continuing on failure
|
|
176
183
|
if (gateResult.status === "failed" && gate.blocking && !options.continueOnFailure) {
|
|
177
|
-
|
|
184
|
+
logger.error(`Stopping pipeline due to blocking gate failure: ${gate.name}`, { gateName: gate.name });
|
|
178
185
|
break;
|
|
179
186
|
}
|
|
180
187
|
} catch (error) {
|
|
181
|
-
|
|
188
|
+
logger.error(`Gate execution error: ${gate.name}`, { gateName: gate.name, error });
|
|
182
189
|
|
|
183
190
|
const errorResult: GateResult = {
|
|
184
191
|
gateId: gate.id,
|
|
@@ -203,7 +210,7 @@ export class SecurityCIPipeline {
|
|
|
203
210
|
|
|
204
211
|
this.reports.push(report);
|
|
205
212
|
|
|
206
|
-
|
|
213
|
+
logger.info(`${stage} gates completed`, { stage, status: overallStatus });
|
|
207
214
|
|
|
208
215
|
return report;
|
|
209
216
|
}
|
|
@@ -224,13 +231,13 @@ export class SecurityCIPipeline {
|
|
|
224
231
|
continue;
|
|
225
232
|
}
|
|
226
233
|
|
|
227
|
-
|
|
234
|
+
logger.info(`Running check: ${check.name}`, { checkName: check.name });
|
|
228
235
|
|
|
229
236
|
try {
|
|
230
237
|
const checkResult = await this.executeSecurityCheck(check, context, options);
|
|
231
238
|
checkResults.push(checkResult);
|
|
232
239
|
} catch (error) {
|
|
233
|
-
|
|
240
|
+
logger.error(`Check execution error: ${check.name}`, { checkName: check.name, error });
|
|
234
241
|
|
|
235
242
|
checkResults.push({
|
|
236
243
|
checkId: check.id,
|
|
@@ -268,7 +275,7 @@ export class SecurityCIPipeline {
|
|
|
268
275
|
): Promise<CheckResult> {
|
|
269
276
|
const startTime = Date.now();
|
|
270
277
|
const findings: SecurityFinding[] = [];
|
|
271
|
-
let score = 100;
|
|
278
|
+
let score: number = 100; // Initialize with safe default
|
|
272
279
|
let details = "";
|
|
273
280
|
|
|
274
281
|
if (options.dryRun) {
|
|
@@ -369,11 +376,17 @@ export class SecurityCIPipeline {
|
|
|
369
376
|
score: number;
|
|
370
377
|
details: string;
|
|
371
378
|
}> {
|
|
379
|
+
const scanParams = check.parameters as {
|
|
380
|
+
targets?: string[];
|
|
381
|
+
depth?: "shallow" | "deep" | "comprehensive";
|
|
382
|
+
includeRuntime?: boolean;
|
|
383
|
+
includeFileSystem?: boolean;
|
|
384
|
+
};
|
|
372
385
|
const scanResult = await this.scanner.performScan({
|
|
373
|
-
targets:
|
|
374
|
-
depth:
|
|
375
|
-
includeRuntime:
|
|
376
|
-
includeFileSystem:
|
|
386
|
+
targets: scanParams.targets ?? ["src/"],
|
|
387
|
+
depth: scanParams.depth ?? "deep",
|
|
388
|
+
includeRuntime: scanParams.includeRuntime ?? false,
|
|
389
|
+
includeFileSystem: scanParams.includeFileSystem ?? true,
|
|
377
390
|
});
|
|
378
391
|
|
|
379
392
|
const findings: SecurityFinding[] = scanResult.vulnerabilities.map((vuln) => ({
|
|
@@ -409,11 +422,12 @@ export class SecurityCIPipeline {
|
|
|
409
422
|
score: number;
|
|
410
423
|
details: string;
|
|
411
424
|
}> {
|
|
425
|
+
const reviewParams = check.parameters as { rules?: string[]; excludeRules?: string[]; aiAnalysis?: boolean };
|
|
412
426
|
const reviewResults = await this.reviewer.reviewDirectory("src/", {
|
|
413
427
|
recursive: true,
|
|
414
|
-
rules:
|
|
415
|
-
excludeRules:
|
|
416
|
-
aiAnalysis:
|
|
428
|
+
rules: reviewParams.rules ?? [],
|
|
429
|
+
excludeRules: reviewParams.excludeRules ?? [],
|
|
430
|
+
aiAnalysis: reviewParams.aiAnalysis ?? false,
|
|
417
431
|
});
|
|
418
432
|
|
|
419
433
|
const allFindings: SecurityFinding[] = [];
|
|
@@ -455,7 +469,7 @@ export class SecurityCIPipeline {
|
|
|
455
469
|
details: string;
|
|
456
470
|
}> {
|
|
457
471
|
// This would integrate with npm audit, Snyk, or similar tools
|
|
458
|
-
|
|
472
|
+
logger.info("Dependency check - integration with external tools required");
|
|
459
473
|
|
|
460
474
|
return {
|
|
461
475
|
findings: [],
|
|
@@ -506,7 +520,7 @@ export class SecurityCIPipeline {
|
|
|
506
520
|
details: string;
|
|
507
521
|
}> {
|
|
508
522
|
// This would integrate with tools like TruffleHog, GitLeaks, etc.
|
|
509
|
-
|
|
523
|
+
logger.info("Secrets check - integration with secret scanning tools required");
|
|
510
524
|
|
|
511
525
|
return {
|
|
512
526
|
findings: [],
|
|
@@ -526,13 +540,14 @@ export class SecurityCIPipeline {
|
|
|
526
540
|
score: number;
|
|
527
541
|
details: string;
|
|
528
542
|
}> {
|
|
529
|
-
|
|
543
|
+
const complianceParams = check.parameters as { frameworks?: string[] };
|
|
544
|
+
const frameworks: string[] = complianceParams.frameworks ?? ["OWASP", "CWE"];
|
|
530
545
|
const findings: SecurityFinding[] = [];
|
|
531
546
|
|
|
532
547
|
// Check for compliance with security frameworks
|
|
533
548
|
for (const framework of frameworks) {
|
|
534
549
|
// This would integrate with compliance checking tools
|
|
535
|
-
|
|
550
|
+
logger.info(`Checking ${framework} compliance`, { framework });
|
|
536
551
|
}
|
|
537
552
|
|
|
538
553
|
return {
|
|
@@ -545,13 +560,11 @@ export class SecurityCIPipeline {
|
|
|
545
560
|
/**
|
|
546
561
|
* Calculate security score for file findings
|
|
547
562
|
*/
|
|
548
|
-
private calculateFileScore(findings:
|
|
549
|
-
const severityWeights = { critical: 20, high: 10, medium: 5, low: 2, info: 1 };
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
return sum + (severityWeights[finding.severity as keyof typeof severityWeights] || 0);
|
|
563
|
+
private calculateFileScore(findings: Array<{ severity: string }>): number {
|
|
564
|
+
const severityWeights: Record<string, number> = { critical: 20, high: 10, medium: 5, low: 2, info: 1 };
|
|
565
|
+
const penalty = findings.reduce((sum: number, finding) => {
|
|
566
|
+
return sum + (severityWeights[finding.severity] || 0);
|
|
553
567
|
}, 0);
|
|
554
|
-
|
|
555
568
|
return Math.max(0, 100 - penalty);
|
|
556
569
|
}
|
|
557
570
|
|
|
@@ -664,7 +677,10 @@ export class SecurityCIPipeline {
|
|
|
664
677
|
/**
|
|
665
678
|
* Generate recommendations based on results
|
|
666
679
|
*/
|
|
667
|
-
private generateRecommendations(
|
|
680
|
+
private generateRecommendations(
|
|
681
|
+
gateResults: GateResult[],
|
|
682
|
+
summary: { criticalIssues: number; highIssues: number; securityScore: number; [key: string]: unknown },
|
|
683
|
+
): string[] {
|
|
668
684
|
const recommendations: string[] = [];
|
|
669
685
|
|
|
670
686
|
if (summary.criticalIssues > 0) {
|
|
@@ -861,7 +877,7 @@ export class SecurityCIPipeline {
|
|
|
861
877
|
const updatedGate = { ...gate, ...updates, id: gateId };
|
|
862
878
|
this.gates.set(gateId, updatedGate);
|
|
863
879
|
|
|
864
|
-
|
|
880
|
+
logger.info(`Updated security gate: ${updatedGate.name}`, { gateName: updatedGate.name });
|
|
865
881
|
return true;
|
|
866
882
|
}
|
|
867
883
|
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { randomBytes } from "crypto";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { LoggerFactory } from "../utils/logger.js";
|
|
8
|
+
|
|
9
|
+
const logger = LoggerFactory.security();
|
|
6
10
|
|
|
7
11
|
export const SecurityConfig = {
|
|
8
12
|
// Rate limiting
|
|
@@ -181,26 +185,26 @@ export class SecurityUtils {
|
|
|
181
185
|
/**
|
|
182
186
|
* Redact sensitive information from objects
|
|
183
187
|
*/
|
|
184
|
-
static redactSensitiveData(obj:
|
|
188
|
+
static redactSensitiveData(obj: unknown): unknown {
|
|
185
189
|
if (typeof obj !== "object" || obj === null) {
|
|
186
190
|
return obj;
|
|
187
191
|
}
|
|
188
192
|
|
|
189
|
-
const
|
|
193
|
+
const working: Record<string, unknown> | unknown[] = Array.isArray(obj) ? [...obj] : { ...(obj as Record<string, unknown>) };
|
|
194
|
+
|
|
195
|
+
if (Array.isArray(working)) {
|
|
196
|
+
return working.map((val) => (typeof val === "object" ? SecurityUtils.redactSensitiveData(val) : val));
|
|
197
|
+
}
|
|
190
198
|
|
|
191
|
-
for (const key in
|
|
192
|
-
if (
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
)
|
|
196
|
-
) {
|
|
197
|
-
redacted[key] = "[REDACTED]";
|
|
198
|
-
} else if (typeof redacted[key] === "object") {
|
|
199
|
-
redacted[key] = SecurityUtils.redactSensitiveData(redacted[key]);
|
|
199
|
+
for (const key in working) {
|
|
200
|
+
if (SecurityConfig.logging.excludeFields.some((field) => key.toLowerCase().includes(field.toLowerCase()))) {
|
|
201
|
+
working[key] = "[REDACTED]";
|
|
202
|
+
} else if (typeof working[key] === "object" && working[key] !== null) {
|
|
203
|
+
working[key] = SecurityUtils.redactSensitiveData(working[key]);
|
|
200
204
|
}
|
|
201
205
|
}
|
|
202
206
|
|
|
203
|
-
return
|
|
207
|
+
return working;
|
|
204
208
|
}
|
|
205
209
|
|
|
206
210
|
/**
|
|
@@ -220,8 +224,7 @@ export class SecurityUtils {
|
|
|
220
224
|
* Generate secure random strings
|
|
221
225
|
*/
|
|
222
226
|
static generateSecureToken(length: number = 32): string {
|
|
223
|
-
const chars =
|
|
224
|
-
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
227
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
225
228
|
const array = new Uint8Array(length);
|
|
226
229
|
|
|
227
230
|
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
@@ -246,7 +249,7 @@ export class SecurityUtils {
|
|
|
246
249
|
/**
|
|
247
250
|
* Sanitize log output
|
|
248
251
|
*/
|
|
249
|
-
static sanitizeForLog(data:
|
|
252
|
+
static sanitizeForLog(data: unknown): unknown {
|
|
250
253
|
if (typeof data === "string") {
|
|
251
254
|
return SecurityUtils.redactString(data);
|
|
252
255
|
}
|
|
@@ -261,28 +264,25 @@ export class SecurityUtils {
|
|
|
261
264
|
* Secure error handler that prevents information disclosure
|
|
262
265
|
*/
|
|
263
266
|
export function createSecureError(
|
|
264
|
-
error:
|
|
267
|
+
error: unknown,
|
|
265
268
|
fallbackMessage: string = SecurityConfig.errorMessages.serverError,
|
|
266
269
|
): Error {
|
|
267
270
|
// Log the actual error for debugging (with sanitization)
|
|
268
271
|
if (process.env.NODE_ENV !== "production") {
|
|
269
|
-
|
|
272
|
+
logger.error("Secure Error", { error: SecurityUtils.sanitizeForLog(error) });
|
|
270
273
|
}
|
|
271
274
|
|
|
272
275
|
// Return generic error to prevent information disclosure
|
|
273
276
|
const secureError = new Error(fallbackMessage);
|
|
274
277
|
|
|
275
278
|
// Preserve error code if it's safe
|
|
276
|
-
if (error && typeof error.code === "string" && !error.code.includes("_")) {
|
|
277
|
-
|
|
279
|
+
if (error && typeof (error as { code?: unknown }).code === "string" && !(error as { code: string }).code.includes("_")) {
|
|
280
|
+
(secureError as unknown as Record<string, unknown>).code = (error as { code: string }).code;
|
|
278
281
|
}
|
|
279
282
|
|
|
280
283
|
return secureError;
|
|
281
284
|
}
|
|
282
285
|
|
|
283
|
-
// Import path for file extension checking
|
|
284
|
-
import * as path from "path";
|
|
285
|
-
|
|
286
286
|
/**
|
|
287
287
|
* Environment-specific security settings
|
|
288
288
|
*/
|