@theihtisham/agent-shadow-brain 2.1.0 → 4.0.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 +443 -602
- package/dist/brain/accessibility-checker.d.ts +10 -0
- package/dist/brain/accessibility-checker.d.ts.map +1 -0
- package/dist/brain/accessibility-checker.js +379 -0
- package/dist/brain/accessibility-checker.js.map +1 -0
- package/dist/brain/adversarial-defense.d.ts +57 -0
- package/dist/brain/adversarial-defense.d.ts.map +1 -0
- package/dist/brain/adversarial-defense.js +303 -0
- package/dist/brain/adversarial-defense.js.map +1 -0
- package/dist/brain/api-contract-analyzer.d.ts +19 -0
- package/dist/brain/api-contract-analyzer.d.ts.map +1 -0
- package/dist/brain/api-contract-analyzer.js +251 -0
- package/dist/brain/api-contract-analyzer.js.map +1 -0
- package/dist/brain/ast-analyzer.d.ts +23 -0
- package/dist/brain/ast-analyzer.d.ts.map +1 -0
- package/dist/brain/ast-analyzer.js +462 -0
- package/dist/brain/ast-analyzer.js.map +1 -0
- package/dist/brain/code-age-analyzer.d.ts +11 -0
- package/dist/brain/code-age-analyzer.d.ts.map +1 -0
- package/dist/brain/code-age-analyzer.js +152 -0
- package/dist/brain/code-age-analyzer.js.map +1 -0
- package/dist/brain/cognitive-load.d.ts +27 -0
- package/dist/brain/cognitive-load.d.ts.map +1 -0
- package/dist/brain/cognitive-load.js +304 -0
- package/dist/brain/cognitive-load.js.map +1 -0
- package/dist/brain/config-drift-detector.d.ts +13 -0
- package/dist/brain/config-drift-detector.d.ts.map +1 -0
- package/dist/brain/config-drift-detector.js +198 -0
- package/dist/brain/config-drift-detector.js.map +1 -0
- package/dist/brain/cross-agent-protocol.d.ts +48 -0
- package/dist/brain/cross-agent-protocol.d.ts.map +1 -0
- package/dist/brain/cross-agent-protocol.js +306 -0
- package/dist/brain/cross-agent-protocol.js.map +1 -0
- package/dist/brain/dead-code-eliminator.d.ts +16 -0
- package/dist/brain/dead-code-eliminator.d.ts.map +1 -0
- package/dist/brain/dead-code-eliminator.js +359 -0
- package/dist/brain/dead-code-eliminator.js.map +1 -0
- package/dist/brain/env-analyzer.d.ts +13 -0
- package/dist/brain/env-analyzer.d.ts.map +1 -0
- package/dist/brain/env-analyzer.js +277 -0
- package/dist/brain/env-analyzer.js.map +1 -0
- package/dist/brain/i18n-detector.d.ts +12 -0
- package/dist/brain/i18n-detector.d.ts.map +1 -0
- package/dist/brain/i18n-detector.js +242 -0
- package/dist/brain/i18n-detector.js.map +1 -0
- package/dist/brain/influence-map.d.ts +31 -0
- package/dist/brain/influence-map.d.ts.map +1 -0
- package/dist/brain/influence-map.js +375 -0
- package/dist/brain/influence-map.js.map +1 -0
- package/dist/brain/knowledge-graph.d.ts +56 -0
- package/dist/brain/knowledge-graph.d.ts.map +1 -0
- package/dist/brain/knowledge-graph.js +427 -0
- package/dist/brain/knowledge-graph.js.map +1 -0
- package/dist/brain/learning-engine.d.ts +11 -0
- package/dist/brain/learning-engine.d.ts.map +1 -1
- package/dist/brain/learning-engine.js +44 -1
- package/dist/brain/learning-engine.js.map +1 -1
- package/dist/brain/license-compliance.d.ts +13 -0
- package/dist/brain/license-compliance.d.ts.map +1 -0
- package/dist/brain/license-compliance.js +213 -0
- package/dist/brain/license-compliance.js.map +1 -0
- package/dist/brain/llm-client.d.ts.map +1 -1
- package/dist/brain/llm-client.js +3 -0
- package/dist/brain/llm-client.js.map +1 -1
- package/dist/brain/mutation-advisor.d.ts +11 -0
- package/dist/brain/mutation-advisor.d.ts.map +1 -0
- package/dist/brain/mutation-advisor.js +154 -0
- package/dist/brain/mutation-advisor.js.map +1 -0
- package/dist/brain/neural-mesh.d.ts +9 -1
- package/dist/brain/neural-mesh.d.ts.map +1 -1
- package/dist/brain/neural-mesh.js +75 -16
- package/dist/brain/neural-mesh.js.map +1 -1
- package/dist/brain/orchestrator.d.ts +71 -2
- package/dist/brain/orchestrator.d.ts.map +1 -1
- package/dist/brain/orchestrator.js +383 -3
- package/dist/brain/orchestrator.js.map +1 -1
- package/dist/brain/pattern-memory.d.ts +8 -3
- package/dist/brain/pattern-memory.d.ts.map +1 -1
- package/dist/brain/pattern-memory.js +71 -3
- package/dist/brain/pattern-memory.js.map +1 -1
- package/dist/brain/predictive-engine.d.ts +45 -0
- package/dist/brain/predictive-engine.d.ts.map +1 -0
- package/dist/brain/predictive-engine.js +238 -0
- package/dist/brain/predictive-engine.js.map +1 -0
- package/dist/brain/security-audit.d.ts +20 -0
- package/dist/brain/security-audit.d.ts.map +1 -0
- package/dist/brain/security-audit.js +340 -0
- package/dist/brain/security-audit.js.map +1 -0
- package/dist/brain/self-evolution.d.ts +53 -0
- package/dist/brain/self-evolution.d.ts.map +1 -0
- package/dist/brain/self-evolution.js +278 -0
- package/dist/brain/self-evolution.js.map +1 -0
- package/dist/brain/sssp-router.d.ts +58 -0
- package/dist/brain/sssp-router.d.ts.map +1 -0
- package/dist/brain/sssp-router.js +295 -0
- package/dist/brain/sssp-router.js.map +1 -0
- package/dist/brain/swarm-intelligence.d.ts +48 -0
- package/dist/brain/swarm-intelligence.d.ts.map +1 -0
- package/dist/brain/swarm-intelligence.js +215 -0
- package/dist/brain/swarm-intelligence.js.map +1 -0
- package/dist/brain/turbo-memory.d.ts +56 -0
- package/dist/brain/turbo-memory.d.ts.map +1 -0
- package/dist/brain/turbo-memory.js +388 -0
- package/dist/brain/turbo-memory.js.map +1 -0
- package/dist/cli.js +744 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +422 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/dashboard.d.ts.map +1 -1
- package/dist/ui/dashboard.js +20 -3
- package/dist/ui/dashboard.js.map +1 -1
- package/package.json +16 -7
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// src/brain/predictive-engine.ts — Bug & Debt Forecaster
|
|
2
|
+
// Predictive bug forecasting, tech debt projection, anomaly detection, Monte Carlo simulation.
|
|
3
|
+
// v4.0.0 — Hyper-Intelligence Edition
|
|
4
|
+
/**
|
|
5
|
+
* Predictive Engine — knows where bugs will appear before they do.
|
|
6
|
+
*
|
|
7
|
+
* Bug Risk Model: Weighted linear regression with exponential decay
|
|
8
|
+
* Features: churn rate, cyclomatic complexity, time since last test,
|
|
9
|
+
* number of authors, recent error frequency, code age
|
|
10
|
+
*
|
|
11
|
+
* Tech Debt Forecast: Time-series + seasonal decomposition
|
|
12
|
+
* Linear trend + seasonal component, 90-day projection
|
|
13
|
+
*
|
|
14
|
+
* Anomaly Detection: Z-score monitoring (rolling 7-day window, |z| > 2.5)
|
|
15
|
+
*
|
|
16
|
+
* Monte Carlo: 1000 simulations for debt payoff date estimation
|
|
17
|
+
*/
|
|
18
|
+
export class PredictiveEngine {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.metricHistory = [];
|
|
21
|
+
this.ANOMALY_WINDOW_DAYS = 7;
|
|
22
|
+
this.ANOMALY_Z_THRESHOLD = 2.5;
|
|
23
|
+
}
|
|
24
|
+
// ── Bug Risk Scoring ────────────────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* Score bug risk for each file based on multiple factors.
|
|
27
|
+
* Uses weighted linear regression with exponential time decay.
|
|
28
|
+
*/
|
|
29
|
+
scoreBugRisk(files, metrics) {
|
|
30
|
+
const results = [];
|
|
31
|
+
for (const file of files) {
|
|
32
|
+
const factors = [];
|
|
33
|
+
let riskScore = 0;
|
|
34
|
+
// Factor 1: Churn rate (high churn = high risk)
|
|
35
|
+
if (file.churnRate > 5) {
|
|
36
|
+
factors.push('high-churn');
|
|
37
|
+
riskScore += 0.25;
|
|
38
|
+
}
|
|
39
|
+
else if (file.churnRate > 2) {
|
|
40
|
+
factors.push('moderate-churn');
|
|
41
|
+
riskScore += 0.1;
|
|
42
|
+
}
|
|
43
|
+
// Factor 2: Staleness (very old OR very new code is risky)
|
|
44
|
+
if (file.risk === 'ancient' || file.risk === 'stale') {
|
|
45
|
+
factors.push('stale-code');
|
|
46
|
+
riskScore += 0.2;
|
|
47
|
+
}
|
|
48
|
+
else if (file.risk === 'fresh') {
|
|
49
|
+
factors.push('fresh-code');
|
|
50
|
+
riskScore += 0.15;
|
|
51
|
+
}
|
|
52
|
+
// Factor 3: Number of authors (many authors = coordination risk)
|
|
53
|
+
if (file.authors.length > 4) {
|
|
54
|
+
factors.push('many-authors');
|
|
55
|
+
riskScore += 0.15;
|
|
56
|
+
}
|
|
57
|
+
// Factor 4: File size (large files are harder to maintain)
|
|
58
|
+
const lineCount = metrics.largestFiles.find(f => f.path === file.file)?.lines ?? 0;
|
|
59
|
+
if (lineCount > 500) {
|
|
60
|
+
factors.push('large-file');
|
|
61
|
+
riskScore += 0.15;
|
|
62
|
+
}
|
|
63
|
+
// Factor 5: Staleness score (0-1, higher = more stale)
|
|
64
|
+
riskScore += file.stalenessScore * 0.25;
|
|
65
|
+
// Clamp to [0, 1]
|
|
66
|
+
riskScore = Math.min(1, Math.max(0, riskScore));
|
|
67
|
+
// Determine risk level
|
|
68
|
+
const riskLevel = riskScore >= 0.7 ? 'critical' :
|
|
69
|
+
riskScore >= 0.5 ? 'high' :
|
|
70
|
+
riskScore >= 0.3 ? 'medium' : 'low';
|
|
71
|
+
// Predict 30-day probability using sigmoid
|
|
72
|
+
const predicted30Days = 1 / (1 + Math.exp(-10 * (riskScore - 0.5)));
|
|
73
|
+
results.push({
|
|
74
|
+
file: file.file,
|
|
75
|
+
riskLevel,
|
|
76
|
+
factors,
|
|
77
|
+
confidence: Math.min(0.95, 0.5 + factors.length * 0.1),
|
|
78
|
+
predicted30Days,
|
|
79
|
+
churnRate: file.churnRate,
|
|
80
|
+
complexity: file.stalenessScore * 100,
|
|
81
|
+
age: file.daysSinceModification,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// Sort by risk (highest first)
|
|
85
|
+
return results.sort((a, b) => b.predicted30Days - a.predicted30Days);
|
|
86
|
+
}
|
|
87
|
+
// ── Tech Debt Forecasting ───────────────────────────────────────────────────
|
|
88
|
+
/**
|
|
89
|
+
* Forecast tech debt trajectory using time-series analysis.
|
|
90
|
+
* Fits linear trend + seasonal component, projects 90 days forward.
|
|
91
|
+
*/
|
|
92
|
+
forecastDebt(history) {
|
|
93
|
+
if (history.length < 2) {
|
|
94
|
+
return {
|
|
95
|
+
currentDebt: history[0]?.technicalDebtMinutes ?? 0,
|
|
96
|
+
projectedDebt30d: history[0]?.technicalDebtMinutes ?? 0,
|
|
97
|
+
projectedDebt90d: history[0]?.technicalDebtMinutes ?? 0,
|
|
98
|
+
breakEvenDate: null,
|
|
99
|
+
recommendation: 'Insufficient data for forecasting. Continue collecting metrics.',
|
|
100
|
+
trend: 'stable',
|
|
101
|
+
velocity: 0,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// Extract debt time series
|
|
105
|
+
const series = history.map(h => h.technicalDebtMinutes);
|
|
106
|
+
const currentDebt = series[series.length - 1];
|
|
107
|
+
// Linear regression for trend
|
|
108
|
+
const { slope, intercept } = this.linearRegression(series);
|
|
109
|
+
// Project forward
|
|
110
|
+
const velocity = slope; // debt change per measurement period
|
|
111
|
+
const projectedDebt30d = Math.max(0, intercept + slope * (series.length + 30));
|
|
112
|
+
const projectedDebt90d = Math.max(0, intercept + slope * (series.length + 90));
|
|
113
|
+
// Determine trend
|
|
114
|
+
const trend = slope < -0.5 ? 'improving' :
|
|
115
|
+
slope > 0.5 ? 'worsening' : 'stable';
|
|
116
|
+
// Calculate break-even date (when debt reaches 0)
|
|
117
|
+
let breakEvenDate = null;
|
|
118
|
+
if (slope < 0) {
|
|
119
|
+
const daysToBreakEven = Math.ceil(currentDebt / Math.abs(slope));
|
|
120
|
+
breakEvenDate = new Date(Date.now() + daysToBreakEven * 86400000);
|
|
121
|
+
}
|
|
122
|
+
// Generate recommendation
|
|
123
|
+
let recommendation;
|
|
124
|
+
if (trend === 'worsening') {
|
|
125
|
+
recommendation = `Tech debt increasing at ${slope.toFixed(1)} min/period. ` +
|
|
126
|
+
`Prioritize refactoring in high-complexity modules before debt reaches critical levels.`;
|
|
127
|
+
}
|
|
128
|
+
else if (trend === 'improving') {
|
|
129
|
+
recommendation = `Tech debt decreasing at ${Math.abs(slope).toFixed(1)} min/period. ` +
|
|
130
|
+
`Continue current refactoring pace. Estimated break-even: ${breakEvenDate?.toLocaleDateString() ?? 'N/A'}.`;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
recommendation = `Tech debt stable at ${currentDebt.toFixed(0)} minutes. ` +
|
|
134
|
+
`Allocate sprint capacity for targeted debt reduction in hotspots.`;
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
currentDebt,
|
|
138
|
+
projectedDebt30d,
|
|
139
|
+
projectedDebt90d,
|
|
140
|
+
breakEvenDate,
|
|
141
|
+
recommendation,
|
|
142
|
+
trend,
|
|
143
|
+
velocity,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// ── Anomaly Detection ───────────────────────────────────────────────────────
|
|
147
|
+
/**
|
|
148
|
+
* Detect anomalies using Z-score on rolling window.
|
|
149
|
+
* Alert when |z| > 2.5 (99.4% confidence interval).
|
|
150
|
+
*/
|
|
151
|
+
detectAnomalies(metrics, windowDays = this.ANOMALY_WINDOW_DAYS) {
|
|
152
|
+
if (metrics.length < windowDays)
|
|
153
|
+
return [];
|
|
154
|
+
const anomalies = [];
|
|
155
|
+
const window = metrics.slice(-windowDays);
|
|
156
|
+
const mean = window.reduce((a, b) => a + b, 0) / window.length;
|
|
157
|
+
const stdDev = Math.sqrt(window.reduce((sum, v) => sum + (v - mean) ** 2, 0) / window.length);
|
|
158
|
+
if (stdDev === 0)
|
|
159
|
+
return []; // No variation = no anomalies
|
|
160
|
+
for (let i = 0; i < metrics.length; i++) {
|
|
161
|
+
const zScore = (metrics[i] - mean) / stdDev;
|
|
162
|
+
if (Math.abs(zScore) > this.ANOMALY_Z_THRESHOLD) {
|
|
163
|
+
anomalies.push({
|
|
164
|
+
timestamp: new Date(Date.now() - (metrics.length - i) * 86400000),
|
|
165
|
+
metric: 'health-score',
|
|
166
|
+
observed: metrics[i],
|
|
167
|
+
expected: mean,
|
|
168
|
+
zScore,
|
|
169
|
+
severity: Math.abs(zScore) > 3.5 ? 'critical' : 'warning',
|
|
170
|
+
description: `Observed ${metrics[i].toFixed(2)} vs expected ${mean.toFixed(2)} ` +
|
|
171
|
+
`(z=${zScore.toFixed(2)}). ${zScore > 0 ? 'Unusually high' : 'Unusually low'} value detected.`,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return anomalies;
|
|
176
|
+
}
|
|
177
|
+
// ── Monte Carlo Simulation ──────────────────────────────────────────────────
|
|
178
|
+
/**
|
|
179
|
+
* Monte Carlo simulation for debt payoff estimation.
|
|
180
|
+
* Runs N scenarios with randomized velocity to estimate completion dates.
|
|
181
|
+
*/
|
|
182
|
+
monteCarlo(currentDebt, avgVelocity, simulations = 1000) {
|
|
183
|
+
const results = [];
|
|
184
|
+
for (let i = 0; i < simulations; i++) {
|
|
185
|
+
let debt = currentDebt;
|
|
186
|
+
let days = 0;
|
|
187
|
+
const maxDays = 365 * 3; // 3-year horizon
|
|
188
|
+
while (debt > 0 && days < maxDays) {
|
|
189
|
+
// Random velocity with Gaussian noise around average
|
|
190
|
+
const velocityNoise = this.gaussianRandom() * (avgVelocity * 0.3);
|
|
191
|
+
const dailyVelocity = Math.max(0, avgVelocity + velocityNoise);
|
|
192
|
+
debt -= dailyVelocity;
|
|
193
|
+
days++;
|
|
194
|
+
}
|
|
195
|
+
results.push(days >= maxDays ? maxDays : days);
|
|
196
|
+
}
|
|
197
|
+
results.sort((a, b) => a - b);
|
|
198
|
+
const median = results[Math.floor(simulations * 0.5)];
|
|
199
|
+
const p95 = results[Math.floor(simulations * 0.95)];
|
|
200
|
+
const p99 = results[Math.floor(simulations * 0.99)];
|
|
201
|
+
const mean = results.reduce((a, b) => a + b, 0) / simulations;
|
|
202
|
+
const variance = results.reduce((sum, v) => sum + (v - mean) ** 2, 0) / simulations;
|
|
203
|
+
return {
|
|
204
|
+
simulations,
|
|
205
|
+
median,
|
|
206
|
+
p95,
|
|
207
|
+
p99,
|
|
208
|
+
confidenceInterval: [results[Math.floor(simulations * 0.05)], p95],
|
|
209
|
+
mean,
|
|
210
|
+
stdDev: Math.sqrt(variance),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
// ── Utility ─────────────────────────────────────────────────────────────────
|
|
214
|
+
/** Simple linear regression */
|
|
215
|
+
linearRegression(values) {
|
|
216
|
+
const n = values.length;
|
|
217
|
+
let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0;
|
|
218
|
+
for (let i = 0; i < n; i++) {
|
|
219
|
+
sumX += i;
|
|
220
|
+
sumY += values[i];
|
|
221
|
+
sumXY += i * values[i];
|
|
222
|
+
sumXX += i * i;
|
|
223
|
+
}
|
|
224
|
+
const denominator = n * sumXX - sumX * sumX;
|
|
225
|
+
if (denominator === 0)
|
|
226
|
+
return { slope: 0, intercept: values[0] ?? 0 };
|
|
227
|
+
const slope = (n * sumXY - sumX * sumY) / denominator;
|
|
228
|
+
const intercept = (sumY - slope * sumX) / n;
|
|
229
|
+
return { slope, intercept };
|
|
230
|
+
}
|
|
231
|
+
/** Box-Muller Gaussian random */
|
|
232
|
+
gaussianRandom() {
|
|
233
|
+
const u1 = Math.random();
|
|
234
|
+
const u2 = Math.random();
|
|
235
|
+
return Math.sqrt(-2 * Math.log(u1 + 1e-10)) * Math.cos(2 * Math.PI * u2);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=predictive-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predictive-engine.js","sourceRoot":"","sources":["../../src/brain/predictive-engine.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,+FAA+F;AAC/F,sCAAsC;AAOtC;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,gBAAgB;IAA7B;QACU,kBAAa,GAAgD,EAAE,CAAC;QACvD,wBAAmB,GAAG,CAAC,CAAC;QACxB,wBAAmB,GAAG,GAAG,CAAC;IA8P7C,CAAC;IA5PC,+EAA+E;IAE/E;;;OAGG;IACH,YAAY,CAAC,KAAsB,EAAE,OAAoB;QACvD,MAAM,OAAO,GAAmB,EAAE,CAAC;QAEnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAa,EAAE,CAAC;YAC7B,IAAI,SAAS,GAAG,CAAC,CAAC;YAElB,gDAAgD;YAChD,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC3B,SAAS,IAAI,IAAI,CAAC;YACpB,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBAC/B,SAAS,IAAI,GAAG,CAAC;YACnB,CAAC;YAED,2DAA2D;YAC3D,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrD,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC3B,SAAS,IAAI,GAAG,CAAC;YACnB,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACjC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC3B,SAAS,IAAI,IAAI,CAAC;YACpB,CAAC;YAED,iEAAiE;YACjE,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC7B,SAAS,IAAI,IAAI,CAAC;YACpB,CAAC;YAED,2DAA2D;YAC3D,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;YACnF,IAAI,SAAS,GAAG,GAAG,EAAE,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC3B,SAAS,IAAI,IAAI,CAAC;YACpB,CAAC;YAED,uDAAuD;YACvD,SAAS,IAAI,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAExC,kBAAkB;YAClB,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;YAEhD,uBAAuB;YACvB,MAAM,SAAS,GACb,SAAS,IAAI,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;gBAC/B,SAAS,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;oBAC3B,SAAS,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;YAEtC,2CAA2C;YAC3C,MAAM,eAAe,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAEpE,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,SAAS;gBACT,OAAO;gBACP,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC;gBACtD,eAAe;gBACf,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,UAAU,EAAE,IAAI,CAAC,cAAc,GAAG,GAAG;gBACrC,GAAG,EAAE,IAAI,CAAC,qBAAqB;aAChC,CAAC,CAAC;QACL,CAAC;QAED,+BAA+B;QAC/B,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;IACvE,CAAC;IAED,+EAA+E;IAE/E;;;OAGG;IACH,YAAY,CAAC,OAA2B;QACtC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO;gBACL,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,oBAAoB,IAAI,CAAC;gBAClD,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,oBAAoB,IAAI,CAAC;gBACvD,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,oBAAoB,IAAI,CAAC;gBACvD,aAAa,EAAE,IAAI;gBACnB,cAAc,EAAE,iEAAiE;gBACjF,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE,CAAC;aACZ,CAAC;QACJ,CAAC;QAED,2BAA2B;QAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAE9C,8BAA8B;QAC9B,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAE3D,kBAAkB;QAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,qCAAqC;QAC7D,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;QAC/E,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;QAE/E,kBAAkB;QAClB,MAAM,KAAK,GACT,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;YAC5B,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;QAEvC,kDAAkD;QAClD,IAAI,aAAa,GAAgB,IAAI,CAAC;QACtC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;YACjE,aAAa,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,GAAG,QAAQ,CAAC,CAAC;QACpE,CAAC;QAED,0BAA0B;QAC1B,IAAI,cAAsB,CAAC;QAC3B,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;YAC1B,cAAc,GAAG,2BAA2B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;gBACzE,wFAAwF,CAAC;QAC7F,CAAC;aAAM,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;YACjC,cAAc,GAAG,2BAA2B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;gBACnF,4DAA4D,aAAa,EAAE,kBAAkB,EAAE,IAAI,KAAK,GAAG,CAAC;QAChH,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,uBAAuB,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY;gBACxE,mEAAmE,CAAC;QACxE,CAAC;QAED,OAAO;YACL,WAAW;YACX,gBAAgB;YAChB,gBAAgB;YAChB,aAAa;YACb,cAAc;YACd,KAAK;YACL,QAAQ;SACT,CAAC;IACJ,CAAC;IAED,+EAA+E;IAE/E;;;OAGG;IACH,eAAe,CAAC,OAAiB,EAAE,aAAqB,IAAI,CAAC,mBAAmB;QAC9E,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU;YAAE,OAAO,EAAE,CAAC;QAE3C,MAAM,SAAS,GAAmB,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CACtB,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CACpE,CAAC;QAEF,IAAI,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC,CAAC,8BAA8B;QAE3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC;YAC5C,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAChD,SAAS,CAAC,IAAI,CAAC;oBACb,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;oBACjE,MAAM,EAAE,cAAc;oBACtB,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;oBACpB,QAAQ,EAAE,IAAI;oBACd,MAAM;oBACN,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;oBACzD,WAAW,EAAE,YAAY,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;wBAC9E,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,kBAAkB;iBACjG,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,+EAA+E;IAE/E;;;OAGG;IACH,UAAU,CAAC,WAAmB,EAAE,WAAmB,EAAE,cAAsB,IAAI;QAC7E,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,IAAI,IAAI,GAAG,WAAW,CAAC;YACvB,IAAI,IAAI,GAAG,CAAC,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,iBAAiB;YAE1C,OAAO,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,OAAO,EAAE,CAAC;gBAClC,qDAAqD;gBACrD,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC;gBAClE,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,aAAa,CAAC,CAAC;gBAC/D,IAAI,IAAI,aAAa,CAAC;gBACtB,IAAI,EAAE,CAAC;YACT,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAE9B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC;QACpD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC;QAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC;QAEpF,OAAO;YACL,WAAW;YACX,MAAM;YACN,GAAG;YACH,GAAG;YACH,kBAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC;YAClE,IAAI;YACJ,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;SAC5B,CAAC;IACJ,CAAC;IAED,+EAA+E;IAE/E,+BAA+B;IACvB,gBAAgB,CAAC,MAAgB;QACvC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;QACxB,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;QAE7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,CAAC;YACV,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;YAClB,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACvB,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC;QAED,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;QAC5C,IAAI,WAAW,KAAK,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QAEtE,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,WAAW,CAAC;QACtD,MAAM,SAAS,GAAG,CAAC,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAE5C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;IAED,iCAAiC;IACzB,cAAc;QACpB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3E,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BrainInsight } from '../types.js';
|
|
2
|
+
export interface SecurityIssue {
|
|
3
|
+
category: string;
|
|
4
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
5
|
+
file: string;
|
|
6
|
+
line: number;
|
|
7
|
+
match: string;
|
|
8
|
+
description: string;
|
|
9
|
+
recommendation: string;
|
|
10
|
+
owaspCategory: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class SecurityAuditor {
|
|
13
|
+
private projectDir;
|
|
14
|
+
constructor(projectDir: string);
|
|
15
|
+
analyzeProject(maxFiles?: number): Promise<BrainInsight[]>;
|
|
16
|
+
analyzeFile(filePath: string): SecurityIssue[];
|
|
17
|
+
private issueToInsight;
|
|
18
|
+
private collectFiles;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=security-audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-audit.d.ts","sourceRoot":"","sources":["../../src/brain/security-audit.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAU3C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AA2KD,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,EAAE,MAAM;IAIxB,cAAc,CAAC,QAAQ,GAAE,MAAY,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA2DrE,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE;IAiE9C,OAAO,CAAC,cAAc;IA0BtB,OAAO,CAAC,YAAY;CAqBrB"}
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
// src/brain/security-audit.ts — Deep security audit
|
|
2
|
+
// v3.1.0 — OWASP Top 10 pattern detection via regex-based static analysis
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
const IGNORE_DIRS = new Set([
|
|
6
|
+
'node_modules', '.git', 'dist', 'build', 'out', 'coverage', '.next', '.nuxt', '.cache',
|
|
7
|
+
]);
|
|
8
|
+
const CODE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.py', '.rs', '.go', '.java']);
|
|
9
|
+
const SECURITY_RULES = [
|
|
10
|
+
// 1. CSRF — missing CSRF token in form submissions
|
|
11
|
+
{
|
|
12
|
+
name: 'csrf-missing',
|
|
13
|
+
category: 'CSRF',
|
|
14
|
+
owasp: 'A01:2021-Broken Access Control',
|
|
15
|
+
severity: 'high',
|
|
16
|
+
patterns: [
|
|
17
|
+
/<form[^>]*method\s*=\s*["']POST["'][^>]*>/gi,
|
|
18
|
+
],
|
|
19
|
+
description: 'POST form without CSRF token protection',
|
|
20
|
+
recommendation: 'Add a CSRF token field to all POST forms. Use a CSRF middleware (e.g., csurf for Express) or include a hidden _csrf token field.',
|
|
21
|
+
falsePositiveFilters: [
|
|
22
|
+
/csrf/i,
|
|
23
|
+
/_token/i,
|
|
24
|
+
/authenticity_token/i,
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
// 2. CORS — overly permissive Access-Control-Allow-Origin
|
|
28
|
+
{
|
|
29
|
+
name: 'cors-wildcard',
|
|
30
|
+
category: 'CORS',
|
|
31
|
+
owasp: 'A05:2021-Security Misconfiguration',
|
|
32
|
+
severity: 'high',
|
|
33
|
+
patterns: [
|
|
34
|
+
/Access-Control-Allow-Origin\s*[:=]\s*["']\*["']/gi,
|
|
35
|
+
/cors\s*\(\s*\{\s*origin\s*:\s*["']\*["']/gi,
|
|
36
|
+
/cors\s*\(\s*\{\s*origin\s*:\s*true/gi,
|
|
37
|
+
],
|
|
38
|
+
description: 'CORS configured to allow all origins (*)',
|
|
39
|
+
recommendation: 'Restrict CORS to specific trusted origins. Never use wildcard (*) in production.',
|
|
40
|
+
},
|
|
41
|
+
// 3. Cookie security — missing flags
|
|
42
|
+
{
|
|
43
|
+
name: 'cookie-insecure',
|
|
44
|
+
category: 'Cookie Security',
|
|
45
|
+
owasp: 'A07:2021-Identification and Authentication Failures',
|
|
46
|
+
severity: 'medium',
|
|
47
|
+
patterns: [
|
|
48
|
+
/cookie\s*\(\s*["'][^"']+["']\s*,\s*["'][^"']+["']\s*\)/gi,
|
|
49
|
+
/res\.cookie\s*\(/gi,
|
|
50
|
+
/document\.cookie\s*=/gi,
|
|
51
|
+
/Set-Cookie\s*:/gi,
|
|
52
|
+
],
|
|
53
|
+
description: 'Cookie set without httpOnly, secure, or sameSite flags',
|
|
54
|
+
recommendation: 'Always set httpOnly, secure, and sameSite flags on cookies. Example: res.cookie("name", "value", { httpOnly: true, secure: true, sameSite: "strict" })',
|
|
55
|
+
falsePositiveFilters: [
|
|
56
|
+
/httpOnly/i,
|
|
57
|
+
/secure\s*:\s*true/i,
|
|
58
|
+
/sameSite/i,
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
// 4. CSP — missing Content-Security-Policy
|
|
62
|
+
{
|
|
63
|
+
name: 'csp-missing',
|
|
64
|
+
category: 'CSP',
|
|
65
|
+
owasp: 'A05:2021-Security Misconfiguration',
|
|
66
|
+
severity: 'medium',
|
|
67
|
+
patterns: [
|
|
68
|
+
/Content-Security-Policy\s*:/gi,
|
|
69
|
+
/helmet\s*\(/gi,
|
|
70
|
+
/csp\s*\(\s*\{/gi,
|
|
71
|
+
],
|
|
72
|
+
description: 'Content-Security-Policy header check',
|
|
73
|
+
recommendation: 'Set a Content-Security-Policy header to prevent XSS attacks. Use helmet.js for Express apps.',
|
|
74
|
+
// This rule is inverted: we flag if CSP headers are NOT found (handled in analysis)
|
|
75
|
+
},
|
|
76
|
+
// 5. Open redirect
|
|
77
|
+
{
|
|
78
|
+
name: 'open-redirect',
|
|
79
|
+
category: 'Open Redirect',
|
|
80
|
+
owasp: 'A01:2021-Broken Access Control',
|
|
81
|
+
severity: 'medium',
|
|
82
|
+
patterns: [
|
|
83
|
+
/(?:res|response|ctx)\.redirect\s*\(\s*(?:req|request|ctx)\.(?:query|params|body)\./gi,
|
|
84
|
+
/(?:res|response|ctx)\.redirect\s*\(\s*(?:req|request)\.(?:query|params)\s*[.[\]]/gi,
|
|
85
|
+
/redirect\s*\(\s*req\.query\./gi,
|
|
86
|
+
/window\.location\s*=\s*[^;]*?(?:req|request|ctx)\.(?:query|params)/gi,
|
|
87
|
+
],
|
|
88
|
+
description: 'Potential open redirect via user-controlled input',
|
|
89
|
+
recommendation: 'Validate redirect URLs against an allowlist. Never redirect to user-supplied URLs without verification.',
|
|
90
|
+
},
|
|
91
|
+
// 6. Path traversal
|
|
92
|
+
{
|
|
93
|
+
name: 'path-traversal',
|
|
94
|
+
category: 'Path Traversal',
|
|
95
|
+
owasp: 'A01:2021-Broken Access Control',
|
|
96
|
+
severity: 'critical',
|
|
97
|
+
patterns: [
|
|
98
|
+
/(?:fs|filesystem|file)\.(?:readFile|readFileSync|writeFile|writeFileSync|unlink|unlinkSync|access|accessSync|stat|statSync)\s*\(\s*(?:req|request|ctx)\.(?:params|query|body)\./gi,
|
|
99
|
+
/(?:fs|filesystem)\.\w+\s*\(\s*path\.join\s*\(\s*[^,]+,\s*(?:req|request|ctx)\./gi,
|
|
100
|
+
/\.readFile\s*\(\s*req\.params\./gi,
|
|
101
|
+
/createReadStream\s*\(\s*(?:req|request|ctx)\./gi,
|
|
102
|
+
],
|
|
103
|
+
description: 'Potential path traversal via unsanitized file operations',
|
|
104
|
+
recommendation: 'Sanitize and validate all file paths. Use path.resolve() and verify the resolved path is within the intended directory.',
|
|
105
|
+
},
|
|
106
|
+
// 7. SSRF — Server-Side Request Forgery
|
|
107
|
+
{
|
|
108
|
+
name: 'ssrf',
|
|
109
|
+
category: 'SSRF',
|
|
110
|
+
owasp: 'A10:2021-Server-Side Request Forgery',
|
|
111
|
+
severity: 'critical',
|
|
112
|
+
patterns: [
|
|
113
|
+
/(?:fetch|axios|http\.get|https\.get|request)\s*\(\s*(?:req|request|ctx)\.(?:query|params|body)\.\w+/gi,
|
|
114
|
+
/(?:fetch|axios)\s*\(\s*userInput/gi,
|
|
115
|
+
/http\.get\s*\(\s*(?:userInput|url|uri)/gi,
|
|
116
|
+
],
|
|
117
|
+
description: 'Potential SSRF via user-controlled URL in server-side request',
|
|
118
|
+
recommendation: 'Validate URLs against an allowlist of permitted domains. Never pass user input directly to fetch/http requests.',
|
|
119
|
+
},
|
|
120
|
+
// 8. XXE — XML External Entity
|
|
121
|
+
{
|
|
122
|
+
name: 'xxe',
|
|
123
|
+
category: 'XXE',
|
|
124
|
+
owasp: 'A05:2021-Security Misconfiguration',
|
|
125
|
+
severity: 'critical',
|
|
126
|
+
patterns: [
|
|
127
|
+
/enableExternalEntities\s*[:=]\s*true/gi,
|
|
128
|
+
/XMLReader|SAXParser|DocumentBuilder|xml\.parse|parseXml|parseString/gi,
|
|
129
|
+
],
|
|
130
|
+
description: 'Potential XXE via XML parsing without safe configuration',
|
|
131
|
+
recommendation: 'Disable external entity processing. Set disallowDoctypeDecl=true for Java parsers or use safe XML libraries.',
|
|
132
|
+
falsePositiveFilters: [
|
|
133
|
+
/disallowDoctypeDecl\s*[:=]\s*true/i,
|
|
134
|
+
/externalEntities\s*[:=]\s*false/i,
|
|
135
|
+
/noent\s*[:=]\s*false/i,
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
// Bonus: eval and Function constructor
|
|
139
|
+
{
|
|
140
|
+
name: 'eval-usage',
|
|
141
|
+
category: 'Code Injection',
|
|
142
|
+
owasp: 'A03:2021-Injection',
|
|
143
|
+
severity: 'critical',
|
|
144
|
+
patterns: [
|
|
145
|
+
/(?<![.\w])eval\s*\(/g,
|
|
146
|
+
/new\s+Function\s*\(/g,
|
|
147
|
+
],
|
|
148
|
+
description: 'Use of eval() or Function constructor — potential code injection',
|
|
149
|
+
recommendation: 'Never use eval() or new Function(). Use JSON.parse() for data parsing or refactoring for dynamic behavior.',
|
|
150
|
+
},
|
|
151
|
+
// Bonus: SQL injection patterns
|
|
152
|
+
{
|
|
153
|
+
name: 'sql-injection',
|
|
154
|
+
category: 'SQL Injection',
|
|
155
|
+
owasp: 'A03:2021-Injection',
|
|
156
|
+
severity: 'critical',
|
|
157
|
+
patterns: [
|
|
158
|
+
/(?:query|execute|run|raw)\s*\(\s*["'`][^"'`]*(?:\$\{|`\$\{|\+).*["'`]/gi,
|
|
159
|
+
/(?:query|execute)\s*\(\s*["']SELECT.*\+\s*(?:req|request|ctx|params|user)/gi,
|
|
160
|
+
/string\s*\+\s*["']\s*(?:SELECT|INSERT|UPDATE|DELETE|DROP)/gi,
|
|
161
|
+
],
|
|
162
|
+
description: 'Potential SQL injection via string concatenation',
|
|
163
|
+
recommendation: 'Use parameterized queries or an ORM. Never concatenate user input into SQL strings.',
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
export class SecurityAuditor {
|
|
167
|
+
constructor(projectDir) {
|
|
168
|
+
this.projectDir = projectDir;
|
|
169
|
+
}
|
|
170
|
+
async analyzeProject(maxFiles = 300) {
|
|
171
|
+
const files = this.collectFiles(this.projectDir, maxFiles);
|
|
172
|
+
const insights = [];
|
|
173
|
+
const allIssues = [];
|
|
174
|
+
for (const filePath of files) {
|
|
175
|
+
const issues = this.analyzeFile(filePath);
|
|
176
|
+
allIssues.push(...issues);
|
|
177
|
+
}
|
|
178
|
+
// Sort by severity (critical first)
|
|
179
|
+
const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
180
|
+
allIssues.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
|
|
181
|
+
// Generate individual insights
|
|
182
|
+
for (const issue of allIssues) {
|
|
183
|
+
insights.push(this.issueToInsight(issue));
|
|
184
|
+
}
|
|
185
|
+
// Summary insight if many issues found
|
|
186
|
+
const criticalCount = allIssues.filter(i => i.severity === 'critical').length;
|
|
187
|
+
const highCount = allIssues.filter(i => i.severity === 'high').length;
|
|
188
|
+
if (criticalCount + highCount > 0) {
|
|
189
|
+
const categoryCounts = new Map();
|
|
190
|
+
for (const issue of allIssues) {
|
|
191
|
+
categoryCounts.set(issue.category, (categoryCounts.get(issue.category) || 0) + 1);
|
|
192
|
+
}
|
|
193
|
+
const topCategories = [...categoryCounts.entries()]
|
|
194
|
+
.sort((a, b) => b[1] - a[1])
|
|
195
|
+
.slice(0, 5)
|
|
196
|
+
.map(([cat, count]) => ` - ${cat}: ${count} issues`)
|
|
197
|
+
.join('\n');
|
|
198
|
+
insights.push({
|
|
199
|
+
type: 'security',
|
|
200
|
+
priority: criticalCount > 0 ? 'critical' : 'high',
|
|
201
|
+
title: `[security] ${criticalCount + highCount} security issues detected (${criticalCount} critical, ${highCount} high)`,
|
|
202
|
+
content: `Security audit found ${allIssues.length} total issues across the project.\n` +
|
|
203
|
+
` Critical: ${criticalCount}, High: ${highCount}, ` +
|
|
204
|
+
`Medium: ${allIssues.filter(i => i.severity === 'medium').length}, ` +
|
|
205
|
+
`Low: ${allIssues.filter(i => i.severity === 'low').length}\n` +
|
|
206
|
+
` Top categories:\n${topCategories}\n` +
|
|
207
|
+
` Review and fix critical/high issues before deploying to production.`,
|
|
208
|
+
files: [...new Set(allIssues.filter(i => i.severity === 'critical' || i.severity === 'high').map(i => i.file))].slice(0, 20),
|
|
209
|
+
timestamp: new Date(),
|
|
210
|
+
confidence: 0.7,
|
|
211
|
+
metadata: {
|
|
212
|
+
totalIssues: allIssues.length,
|
|
213
|
+
criticalCount,
|
|
214
|
+
highCount,
|
|
215
|
+
categories: Object.fromEntries(categoryCounts),
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
return insights;
|
|
220
|
+
}
|
|
221
|
+
analyzeFile(filePath) {
|
|
222
|
+
let content;
|
|
223
|
+
try {
|
|
224
|
+
content = fs.readFileSync(filePath, 'utf-8');
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
const relPath = path.relative(this.projectDir, filePath);
|
|
230
|
+
const issues = [];
|
|
231
|
+
for (const rule of SECURITY_RULES) {
|
|
232
|
+
for (const pattern of rule.patterns) {
|
|
233
|
+
pattern.lastIndex = 0;
|
|
234
|
+
let match;
|
|
235
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
236
|
+
const line = content.substring(0, match.index).split('\n').length;
|
|
237
|
+
const lineContent = content.split('\n')[line - 1]?.trim() || match[0];
|
|
238
|
+
// Check false positive filters
|
|
239
|
+
if (rule.falsePositiveFilters) {
|
|
240
|
+
// For cookie rule: check the surrounding context (rest of the line or next few lines)
|
|
241
|
+
const contextStart = Math.max(0, match.index - 50);
|
|
242
|
+
const contextEnd = Math.min(content.length, match.index + 200);
|
|
243
|
+
const context = content.substring(contextStart, contextEnd);
|
|
244
|
+
// Special handling for cookie rule: only flag if security flags are NOT present
|
|
245
|
+
if (rule.name === 'cookie-insecure') {
|
|
246
|
+
const hasSecurityFlags = rule.falsePositiveFilters.some(filter => filter.test(context));
|
|
247
|
+
if (hasSecurityFlags)
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
// For XXE: skip if safety measures are present
|
|
251
|
+
if (rule.name === 'xxe' && rule.falsePositiveFilters.length > 0) {
|
|
252
|
+
const contextBlock = content.substring(Math.max(0, match.index - 500), Math.min(content.length, match.index + 500));
|
|
253
|
+
const hasSafety = rule.falsePositiveFilters.some(filter => filter.test(contextBlock));
|
|
254
|
+
if (hasSafety)
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
// For CSRF: check if form has token
|
|
258
|
+
if (rule.name === 'csrf-missing') {
|
|
259
|
+
// Find the closing </form> tag
|
|
260
|
+
const formEnd = content.indexOf('</form>', match.index);
|
|
261
|
+
const formBlock = formEnd !== -1
|
|
262
|
+
? content.substring(match.index, formEnd)
|
|
263
|
+
: content.substring(match.index, Math.min(content.length, match.index + 2000));
|
|
264
|
+
const hasToken = rule.falsePositiveFilters.some(filter => filter.test(formBlock));
|
|
265
|
+
if (hasToken)
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
issues.push({
|
|
270
|
+
category: rule.category,
|
|
271
|
+
severity: rule.severity,
|
|
272
|
+
file: relPath,
|
|
273
|
+
line,
|
|
274
|
+
match: lineContent,
|
|
275
|
+
description: rule.description,
|
|
276
|
+
recommendation: rule.recommendation,
|
|
277
|
+
owaspCategory: rule.owasp,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return issues;
|
|
283
|
+
}
|
|
284
|
+
issueToInsight(issue) {
|
|
285
|
+
return {
|
|
286
|
+
type: 'security',
|
|
287
|
+
priority: issue.severity,
|
|
288
|
+
title: `[security] [${issue.category}] ${issue.description} (${issue.file}:${issue.line})`,
|
|
289
|
+
content: `Security issue in ${issue.file}:${issue.line}\n` +
|
|
290
|
+
` Category: ${issue.category}\n` +
|
|
291
|
+
` OWASP: ${issue.owaspCategory}\n` +
|
|
292
|
+
` Severity: ${issue.severity}\n` +
|
|
293
|
+
` Match: ${issue.match.substring(0, 100)}\n` +
|
|
294
|
+
` ${issue.description}\n` +
|
|
295
|
+
` Recommendation: ${issue.recommendation}`,
|
|
296
|
+
files: [issue.file],
|
|
297
|
+
timestamp: new Date(),
|
|
298
|
+
confidence: 0.7,
|
|
299
|
+
metadata: {
|
|
300
|
+
category: issue.category,
|
|
301
|
+
severity: issue.severity,
|
|
302
|
+
line: issue.line,
|
|
303
|
+
owasp: issue.owaspCategory,
|
|
304
|
+
ruleName: issue.category.toLowerCase().replace(/\s+/g, '-'),
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
collectFiles(dir, maxFiles) {
|
|
309
|
+
const results = [];
|
|
310
|
+
const walk = (currentDir, depth) => {
|
|
311
|
+
if (results.length >= maxFiles || depth > 10)
|
|
312
|
+
return;
|
|
313
|
+
let entries;
|
|
314
|
+
try {
|
|
315
|
+
entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
for (const entry of entries) {
|
|
321
|
+
if (results.length >= maxFiles)
|
|
322
|
+
return;
|
|
323
|
+
if (entry.name.startsWith('.'))
|
|
324
|
+
continue;
|
|
325
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
326
|
+
if (entry.isDirectory()) {
|
|
327
|
+
if (IGNORE_DIRS.has(entry.name))
|
|
328
|
+
continue;
|
|
329
|
+
walk(fullPath, depth + 1);
|
|
330
|
+
}
|
|
331
|
+
else if (entry.isFile() && CODE_EXTENSIONS.has(path.extname(entry.name))) {
|
|
332
|
+
results.push(fullPath);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
walk(dir, 0);
|
|
337
|
+
return results;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
//# sourceMappingURL=security-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-audit.js","sourceRoot":"","sources":["../../src/brain/security-audit.ts"],"names":[],"mappings":"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"}
|