@barissozen/csns 0.7.5 → 0.7.7
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 +215 -225
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +1 -0
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/tracer/index.d.ts +2 -0
- package/dist/agent/tracer/index.d.ts.map +1 -1
- package/dist/agent/tracer/index.js +1 -0
- package/dist/agent/tracer/index.js.map +1 -1
- package/dist/agent/tracer/security-scanner.d.ts +54 -0
- package/dist/agent/tracer/security-scanner.d.ts.map +1 -0
- package/dist/agent/tracer/security-scanner.js +397 -0
- package/dist/agent/tracer/security-scanner.js.map +1 -0
- package/dist/orchestrator/entity-detector.d.ts +52 -0
- package/dist/orchestrator/entity-detector.d.ts.map +1 -0
- package/dist/orchestrator/entity-detector.js +297 -0
- package/dist/orchestrator/entity-detector.js.map +1 -0
- package/dist/orchestrator/index.d.ts +2 -0
- package/dist/orchestrator/index.d.ts.map +1 -1
- package/dist/orchestrator/index.js +2 -0
- package/dist/orchestrator/index.js.map +1 -1
- package/dist/orchestrator/smart-scaffold.d.ts +36 -0
- package/dist/orchestrator/smart-scaffold.d.ts.map +1 -0
- package/dist/orchestrator/smart-scaffold.js +438 -0
- package/dist/orchestrator/smart-scaffold.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Scanner — Automated Security Vulnerability Detection
|
|
3
|
+
*
|
|
4
|
+
* Finds the vulnerabilities that structural audit can't:
|
|
5
|
+
* - Non-null env assertions without validation (crash risk)
|
|
6
|
+
* - JSON.parse without try/catch (crash risk)
|
|
7
|
+
* - Hardcoded secrets
|
|
8
|
+
* - SQL string concatenation (injection risk)
|
|
9
|
+
* - Weak CSP directives
|
|
10
|
+
* - Missing CORS origin
|
|
11
|
+
* - Exposed stack traces
|
|
12
|
+
* - Cookie/JWT TTL mismatches (cross-file value checker)
|
|
13
|
+
* - Dead imports
|
|
14
|
+
*
|
|
15
|
+
* Tested against real findings from manual Cayman-Hashlock audit.
|
|
16
|
+
*/
|
|
17
|
+
export type SecuritySeverity = 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
18
|
+
export interface SecurityFinding {
|
|
19
|
+
id: string;
|
|
20
|
+
rule: string;
|
|
21
|
+
severity: SecuritySeverity;
|
|
22
|
+
file: string;
|
|
23
|
+
line: number;
|
|
24
|
+
code: string;
|
|
25
|
+
description: string;
|
|
26
|
+
fix: string;
|
|
27
|
+
}
|
|
28
|
+
export interface SecurityReport {
|
|
29
|
+
findings: SecurityFinding[];
|
|
30
|
+
summary: {
|
|
31
|
+
total: number;
|
|
32
|
+
critical: number;
|
|
33
|
+
high: number;
|
|
34
|
+
medium: number;
|
|
35
|
+
low: number;
|
|
36
|
+
info: number;
|
|
37
|
+
securityScore: number;
|
|
38
|
+
};
|
|
39
|
+
scannedFiles: number;
|
|
40
|
+
duration: number;
|
|
41
|
+
}
|
|
42
|
+
export declare class SecurityScanner {
|
|
43
|
+
private projectRoot;
|
|
44
|
+
constructor(projectRoot: string);
|
|
45
|
+
scan(): Promise<SecurityReport>;
|
|
46
|
+
private detectValueMismatches;
|
|
47
|
+
private computeScore;
|
|
48
|
+
private deduplicate;
|
|
49
|
+
private getLineNumber;
|
|
50
|
+
private isTestFile;
|
|
51
|
+
private collectFiles;
|
|
52
|
+
private walk;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=security-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-scanner.d.ts","sourceRoot":"","sources":["../../../src/agent/tracer/security-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AASH,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAE/E,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA8ND,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,EAAE,MAAM;IAIzB,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC;IA2HrC,OAAO,CAAC,qBAAqB;IAgC7B,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,UAAU;YAKJ,YAAY;YAMZ,IAAI;CAYnB"}
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Scanner — Automated Security Vulnerability Detection
|
|
3
|
+
*
|
|
4
|
+
* Finds the vulnerabilities that structural audit can't:
|
|
5
|
+
* - Non-null env assertions without validation (crash risk)
|
|
6
|
+
* - JSON.parse without try/catch (crash risk)
|
|
7
|
+
* - Hardcoded secrets
|
|
8
|
+
* - SQL string concatenation (injection risk)
|
|
9
|
+
* - Weak CSP directives
|
|
10
|
+
* - Missing CORS origin
|
|
11
|
+
* - Exposed stack traces
|
|
12
|
+
* - Cookie/JWT TTL mismatches (cross-file value checker)
|
|
13
|
+
* - Dead imports
|
|
14
|
+
*
|
|
15
|
+
* Tested against real findings from manual Cayman-Hashlock audit.
|
|
16
|
+
*/
|
|
17
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
18
|
+
import { join, relative, extname } from 'node:path';
|
|
19
|
+
const RULES = [
|
|
20
|
+
// ── Crash Risks ──────────────────────────────────────
|
|
21
|
+
{
|
|
22
|
+
id: 'SEC-01',
|
|
23
|
+
name: 'non-null-env-assertion',
|
|
24
|
+
severity: 'medium',
|
|
25
|
+
pattern: /process\.env\[?['"]?\w+['"]?\]?!/g,
|
|
26
|
+
antiPattern: /if\s*\(!?\s*process\.env|const\s+\w+\s*=\s*process\.env[^!]|process\.env\.\w+\s*\?\?|process\.env\.\w+\s*\|\|/,
|
|
27
|
+
description: 'Non-null assertion on process.env without prior validation — crashes with cryptic error if env var is missing',
|
|
28
|
+
fix: 'Add startup validation: const X = process.env.X; if (!X) throw new Error("X is required");',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'SEC-02',
|
|
32
|
+
name: 'json-parse-no-try-catch',
|
|
33
|
+
severity: 'medium',
|
|
34
|
+
pattern: /JSON\.parse\s*\(\s*(?:process\.env|req\.|request\.|body|params|query|headers)/g,
|
|
35
|
+
antiPattern: /try\s*{[^}]*JSON\.parse/,
|
|
36
|
+
description: 'JSON.parse on untrusted input without try/catch — malformed input crashes the process',
|
|
37
|
+
fix: 'Wrap in try/catch or use a safe parse utility (e.g., zod .safeParse())',
|
|
38
|
+
},
|
|
39
|
+
// ── Secrets ──────────────────────────────────────────
|
|
40
|
+
{
|
|
41
|
+
id: 'SEC-03',
|
|
42
|
+
name: 'hardcoded-secret',
|
|
43
|
+
severity: 'critical',
|
|
44
|
+
pattern: /(?:password|secret|apikey|api_key|token|private_key)\s*[:=]\s*['"][^'"]{8,}['"]/gi,
|
|
45
|
+
antiPattern: /process\.env|example|placeholder|TODO|CHANGE|test|mock|fake|dummy|sample/i,
|
|
46
|
+
description: 'Possible hardcoded secret in source code',
|
|
47
|
+
fix: 'Move to environment variable or secrets manager',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: 'SEC-04',
|
|
51
|
+
name: 'hardcoded-jwt-secret',
|
|
52
|
+
severity: 'critical',
|
|
53
|
+
pattern: /jwt\.sign\s*\([^)]*['"][a-zA-Z0-9+/=]{16,}['"]/g,
|
|
54
|
+
description: 'Hardcoded JWT signing secret in jwt.sign() call',
|
|
55
|
+
fix: 'Use process.env.JWT_SECRET with startup validation',
|
|
56
|
+
},
|
|
57
|
+
// ── SQL Injection ────────────────────────────────────
|
|
58
|
+
{
|
|
59
|
+
id: 'SEC-05',
|
|
60
|
+
name: 'sql-string-concat',
|
|
61
|
+
severity: 'critical',
|
|
62
|
+
pattern: /(?:query|execute|raw)\s*\(\s*`[^`]*\$\{(?!.*params|.*where|.*conditions|.*clause)/g,
|
|
63
|
+
antiPattern: /\$\d+|_patches|\.test\.|\.spec\./,
|
|
64
|
+
description: 'SQL query with template literal interpolation — potential SQL injection',
|
|
65
|
+
fix: 'Use parameterized queries: query("SELECT * FROM x WHERE id = $1", [id])',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 'SEC-06',
|
|
69
|
+
name: 'sql-string-concat-plus',
|
|
70
|
+
severity: 'critical',
|
|
71
|
+
pattern: /(?:query|execute|raw)\s*\(\s*['"][^'"]*['"]\s*\+\s*(?:req\.|args\.|params\.|body\.|input)/g,
|
|
72
|
+
description: 'SQL query built with string concatenation from user input',
|
|
73
|
+
fix: 'Use parameterized queries instead of string concatenation',
|
|
74
|
+
},
|
|
75
|
+
// ── CSP / Headers ────────────────────────────────────
|
|
76
|
+
{
|
|
77
|
+
id: 'SEC-07',
|
|
78
|
+
name: 'csp-unsafe-inline',
|
|
79
|
+
severity: 'low',
|
|
80
|
+
pattern: /(?:script-src|style-src)[^;]*'unsafe-inline'/g,
|
|
81
|
+
description: 'CSP allows unsafe-inline — enables XSS via inline scripts/styles',
|
|
82
|
+
fix: 'Use nonce-based or hash-based CSP instead of unsafe-inline',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: 'SEC-08',
|
|
86
|
+
name: 'csp-unsafe-eval',
|
|
87
|
+
severity: 'medium',
|
|
88
|
+
pattern: /(?:script-src)[^;]*'unsafe-eval'/g,
|
|
89
|
+
description: 'CSP allows unsafe-eval — enables code injection via eval()',
|
|
90
|
+
fix: 'Remove unsafe-eval from CSP; refactor code to avoid eval()',
|
|
91
|
+
},
|
|
92
|
+
// ── CORS ─────────────────────────────────────────────
|
|
93
|
+
{
|
|
94
|
+
id: 'SEC-09',
|
|
95
|
+
name: 'cors-wildcard',
|
|
96
|
+
severity: 'medium',
|
|
97
|
+
pattern: /cors\s*\(\s*\)|origin\s*:\s*['"]?\*['"]?|Access-Control-Allow-Origin.*\*/g,
|
|
98
|
+
antiPattern: /NODE_ENV.*(?:dev|test)|development/,
|
|
99
|
+
description: 'CORS allows all origins — any website can make authenticated requests',
|
|
100
|
+
fix: 'Restrict origin to specific allowed domains',
|
|
101
|
+
},
|
|
102
|
+
// ── Error Exposure ───────────────────────────────────
|
|
103
|
+
{
|
|
104
|
+
id: 'SEC-10',
|
|
105
|
+
name: 'exposed-stack-trace',
|
|
106
|
+
severity: 'low',
|
|
107
|
+
pattern: /res\.(?:send|json)\s*\(\s*(?:err|error)(?:\.stack|\.message|\))/g,
|
|
108
|
+
antiPattern: /NODE_ENV.*prod|production/,
|
|
109
|
+
description: 'Raw error/stack trace sent in HTTP response — leaks internal details',
|
|
110
|
+
fix: 'Return generic error message in production; log full error server-side',
|
|
111
|
+
},
|
|
112
|
+
// ── Auth ─────────────────────────────────────────────
|
|
113
|
+
{
|
|
114
|
+
id: 'SEC-11',
|
|
115
|
+
name: 'jwt-alg-none',
|
|
116
|
+
severity: 'critical',
|
|
117
|
+
pattern: /algorithms?\s*:\s*\[?\s*['"]none['"]/gi,
|
|
118
|
+
description: 'JWT configured to accept "none" algorithm — allows unsigned tokens',
|
|
119
|
+
fix: 'Never allow alg: none; always specify: algorithms: ["HS256"]',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'SEC-12',
|
|
123
|
+
name: 'eval-usage',
|
|
124
|
+
severity: 'high',
|
|
125
|
+
pattern: /\beval\s*\(/g,
|
|
126
|
+
antiPattern: /\/\/.*eval|eslint-disable|\.test\.|\.spec\./,
|
|
127
|
+
description: 'eval() usage — allows arbitrary code execution',
|
|
128
|
+
fix: 'Replace eval with JSON.parse, Function constructor, or domain-specific parser',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
id: 'SEC-13',
|
|
132
|
+
name: 'innerhtml-usage',
|
|
133
|
+
severity: 'high',
|
|
134
|
+
pattern: /\.innerHTML\s*=|dangerouslySetInnerHTML/g,
|
|
135
|
+
antiPattern: /sanitize|DOMPurify|xss/i,
|
|
136
|
+
description: 'innerHTML/dangerouslySetInnerHTML usage — XSS risk if input not sanitized',
|
|
137
|
+
fix: 'Use textContent, or sanitize with DOMPurify before setting innerHTML',
|
|
138
|
+
},
|
|
139
|
+
// ── Dead Import ──────────────────────────────────────
|
|
140
|
+
{
|
|
141
|
+
id: 'SEC-14',
|
|
142
|
+
name: 'unused-import-hint',
|
|
143
|
+
severity: 'info',
|
|
144
|
+
pattern: /import\s+{?\s*(\w+).*}\s+from/g,
|
|
145
|
+
// This is a hint — real detection needs usage check (below)
|
|
146
|
+
description: 'Potential unused import',
|
|
147
|
+
fix: 'Remove if unused — reduces attack surface and bundle size',
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
/** Patterns to extract related values across files */
|
|
151
|
+
const VALUE_PATTERNS = [
|
|
152
|
+
{
|
|
153
|
+
key: 'access-token-ttl',
|
|
154
|
+
pattern: /(?:ACCESS_TOKEN_TTL|access.*ttl|token.*expir(?:es|y|ation)|maxAge|max_age)\s*[:=]\s*['"]?(\d+[smhd]?|\d+\s*\*\s*\d+)['"]?/gi,
|
|
155
|
+
extractValue: (m) => {
|
|
156
|
+
const raw = m[1];
|
|
157
|
+
if (!raw)
|
|
158
|
+
return null;
|
|
159
|
+
return { value: raw, unit: 'time' };
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
key: 'refresh-token-ttl',
|
|
164
|
+
pattern: /(?:REFRESH_TOKEN_TTL|refresh.*ttl|refresh.*expir)\s*[:=]\s*['"]?(\d+[smhd]?|\d+\s*\*\s*\d+)['"]?/gi,
|
|
165
|
+
extractValue: (m) => {
|
|
166
|
+
const raw = m[1];
|
|
167
|
+
if (!raw)
|
|
168
|
+
return null;
|
|
169
|
+
return { value: raw, unit: 'time' };
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
key: 'cookie-max-age',
|
|
174
|
+
pattern: /maxAge\s*:\s*(\d+(?:\s*\*\s*\d+)*)/g,
|
|
175
|
+
extractValue: (m) => {
|
|
176
|
+
const raw = m[1];
|
|
177
|
+
if (!raw)
|
|
178
|
+
return null;
|
|
179
|
+
try {
|
|
180
|
+
// eslint-disable-next-line no-eval
|
|
181
|
+
const val = Function(`"use strict"; return (${raw})`)();
|
|
182
|
+
return { value: val, unit: 'seconds' };
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return { value: raw, unit: 'expression' };
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
// ═══════════════════════════════════════════════════════════
|
|
191
|
+
// Scanner
|
|
192
|
+
// ═══════════════════════════════════════════════════════════
|
|
193
|
+
const SOURCE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']);
|
|
194
|
+
const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.turbo']);
|
|
195
|
+
export class SecurityScanner {
|
|
196
|
+
projectRoot;
|
|
197
|
+
constructor(projectRoot) {
|
|
198
|
+
this.projectRoot = projectRoot;
|
|
199
|
+
}
|
|
200
|
+
async scan() {
|
|
201
|
+
const start = Date.now();
|
|
202
|
+
const files = await this.collectFiles();
|
|
203
|
+
const findings = [];
|
|
204
|
+
const valueExtractions = [];
|
|
205
|
+
let findingCounter = 0;
|
|
206
|
+
for (const file of files) {
|
|
207
|
+
let content;
|
|
208
|
+
try {
|
|
209
|
+
content = await readFile(join(this.projectRoot, file), 'utf-8');
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const lines = content.split('\n');
|
|
215
|
+
// Run security rules
|
|
216
|
+
for (const rule of RULES) {
|
|
217
|
+
// Skip unused-import-hint (handled separately below)
|
|
218
|
+
if (rule.id === 'SEC-14')
|
|
219
|
+
continue;
|
|
220
|
+
// Check anti-pattern on whole file first
|
|
221
|
+
if (rule.antiPattern) {
|
|
222
|
+
// For some rules, anti-pattern means "this file has proper handling"
|
|
223
|
+
// We check per-match below for more precision
|
|
224
|
+
}
|
|
225
|
+
const regex = new RegExp(rule.pattern.source, rule.pattern.flags);
|
|
226
|
+
let match;
|
|
227
|
+
while ((match = regex.exec(content)) !== null) {
|
|
228
|
+
const lineNum = this.getLineNumber(content, match.index);
|
|
229
|
+
const codeLine = lines[lineNum - 1]?.trim() ?? '';
|
|
230
|
+
// Per-line anti-pattern check
|
|
231
|
+
if (rule.antiPattern) {
|
|
232
|
+
// Check surrounding context (5 lines before)
|
|
233
|
+
const contextStart = Math.max(0, lineNum - 6);
|
|
234
|
+
const context = lines.slice(contextStart, lineNum).join('\n');
|
|
235
|
+
if (rule.antiPattern.test(context) || rule.antiPattern.test(codeLine)) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// Skip test files for most rules
|
|
240
|
+
if (this.isTestFile(file) && rule.severity !== 'critical')
|
|
241
|
+
continue;
|
|
242
|
+
// Skip test files for hardcoded secret rules — test fixtures are expected
|
|
243
|
+
if (this.isTestFile(file) && (rule.id === 'SEC-03' || rule.id === 'SEC-04'))
|
|
244
|
+
continue;
|
|
245
|
+
findings.push({
|
|
246
|
+
id: `F${++findingCounter}`,
|
|
247
|
+
rule: rule.id,
|
|
248
|
+
severity: rule.severity,
|
|
249
|
+
file,
|
|
250
|
+
line: lineNum,
|
|
251
|
+
code: codeLine.slice(0, 150),
|
|
252
|
+
description: rule.description,
|
|
253
|
+
fix: rule.fix,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Extract values for cross-file mismatch detection
|
|
258
|
+
for (const vp of VALUE_PATTERNS) {
|
|
259
|
+
const regex = new RegExp(vp.pattern.source, vp.pattern.flags);
|
|
260
|
+
let match;
|
|
261
|
+
while ((match = regex.exec(content)) !== null) {
|
|
262
|
+
const extracted = vp.extractValue(match);
|
|
263
|
+
if (extracted) {
|
|
264
|
+
valueExtractions.push({
|
|
265
|
+
file,
|
|
266
|
+
line: this.getLineNumber(content, match.index),
|
|
267
|
+
key: vp.key,
|
|
268
|
+
...extracted,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// Cross-file value mismatch detection
|
|
275
|
+
const mismatches = this.detectValueMismatches(valueExtractions);
|
|
276
|
+
for (const mismatch of mismatches) {
|
|
277
|
+
findings.push({
|
|
278
|
+
id: `F${++findingCounter}`,
|
|
279
|
+
rule: 'SEC-XVAL',
|
|
280
|
+
severity: 'low',
|
|
281
|
+
file: mismatch.values.map(v => v.file).join(' ↔ '),
|
|
282
|
+
line: mismatch.values[0]?.line ?? 0,
|
|
283
|
+
code: mismatch.values.map(v => `${v.file}:${v.line} → ${v.value}`).join(' | '),
|
|
284
|
+
description: mismatch.description,
|
|
285
|
+
fix: 'Ensure related values are consistent; extract to shared constant',
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
// Deduplicate (same rule + same file + same line)
|
|
289
|
+
const deduped = this.deduplicate(findings);
|
|
290
|
+
// Sort by severity
|
|
291
|
+
const severityOrder = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
|
|
292
|
+
deduped.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
|
|
293
|
+
const summary = {
|
|
294
|
+
total: deduped.length,
|
|
295
|
+
critical: deduped.filter(f => f.severity === 'critical').length,
|
|
296
|
+
high: deduped.filter(f => f.severity === 'high').length,
|
|
297
|
+
medium: deduped.filter(f => f.severity === 'medium').length,
|
|
298
|
+
low: deduped.filter(f => f.severity === 'low').length,
|
|
299
|
+
info: deduped.filter(f => f.severity === 'info').length,
|
|
300
|
+
securityScore: this.computeScore(deduped),
|
|
301
|
+
};
|
|
302
|
+
return {
|
|
303
|
+
findings: deduped,
|
|
304
|
+
summary,
|
|
305
|
+
scannedFiles: files.length,
|
|
306
|
+
duration: Date.now() - start,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
// ═══════════════════════════════════════════════════════════
|
|
310
|
+
// Helpers
|
|
311
|
+
// ═══════════════════════════════════════════════════════════
|
|
312
|
+
detectValueMismatches(extractions) {
|
|
313
|
+
const mismatches = [];
|
|
314
|
+
// Group by key
|
|
315
|
+
const byKey = new Map();
|
|
316
|
+
for (const e of extractions) {
|
|
317
|
+
if (!byKey.has(e.key))
|
|
318
|
+
byKey.set(e.key, []);
|
|
319
|
+
byKey.get(e.key).push(e);
|
|
320
|
+
}
|
|
321
|
+
// Check access-token-ttl vs cookie-max-age
|
|
322
|
+
const tokenTTLs = byKey.get('access-token-ttl') ?? [];
|
|
323
|
+
const cookieMaxAges = byKey.get('cookie-max-age') ?? [];
|
|
324
|
+
if (tokenTTLs.length > 0 && cookieMaxAges.length > 0) {
|
|
325
|
+
// Simple heuristic: if values look different and are from different files
|
|
326
|
+
const tokenFiles = new Set(tokenTTLs.map(t => t.file));
|
|
327
|
+
const cookieFiles = new Set(cookieMaxAges.map(c => c.file));
|
|
328
|
+
const crossFile = [...cookieFiles].some(f => !tokenFiles.has(f));
|
|
329
|
+
if (crossFile) {
|
|
330
|
+
mismatches.push({
|
|
331
|
+
key: 'token-ttl-vs-cookie-maxage',
|
|
332
|
+
values: [...tokenTTLs, ...cookieMaxAges],
|
|
333
|
+
description: `Token TTL and cookie maxAge defined in different files — values may be mismatched. Token: ${tokenTTLs.map(t => `${t.value} (${t.file}:${t.line})`).join(', ')}. Cookie: ${cookieMaxAges.map(c => `${c.value} (${c.file}:${c.line})`).join(', ')}`,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return mismatches;
|
|
338
|
+
}
|
|
339
|
+
computeScore(findings) {
|
|
340
|
+
let score = 100;
|
|
341
|
+
score -= findings.filter(f => f.severity === 'critical').length * 20;
|
|
342
|
+
score -= findings.filter(f => f.severity === 'high').length * 10;
|
|
343
|
+
score -= findings.filter(f => f.severity === 'medium').length * 5;
|
|
344
|
+
score -= findings.filter(f => f.severity === 'low').length * 2;
|
|
345
|
+
score -= findings.filter(f => f.severity === 'info').length * 0.5;
|
|
346
|
+
return Math.max(0, Math.min(100, score));
|
|
347
|
+
}
|
|
348
|
+
deduplicate(findings) {
|
|
349
|
+
const seen = new Set();
|
|
350
|
+
return findings.filter(f => {
|
|
351
|
+
const key = `${f.rule}:${f.file}:${f.line}`;
|
|
352
|
+
if (seen.has(key))
|
|
353
|
+
return false;
|
|
354
|
+
seen.add(key);
|
|
355
|
+
return true;
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
getLineNumber(content, charIndex) {
|
|
359
|
+
let count = 0;
|
|
360
|
+
const lines = content.split('\n');
|
|
361
|
+
for (let i = 0; i < lines.length; i++) {
|
|
362
|
+
count += lines[i].length + 1;
|
|
363
|
+
if (count > charIndex)
|
|
364
|
+
return i + 1;
|
|
365
|
+
}
|
|
366
|
+
return lines.length;
|
|
367
|
+
}
|
|
368
|
+
isTestFile(file) {
|
|
369
|
+
return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(file) ||
|
|
370
|
+
/__tests__\//.test(file) || /\btests?\//.test(file);
|
|
371
|
+
}
|
|
372
|
+
async collectFiles() {
|
|
373
|
+
const files = [];
|
|
374
|
+
await this.walk(this.projectRoot, files);
|
|
375
|
+
return files;
|
|
376
|
+
}
|
|
377
|
+
async walk(dir, files) {
|
|
378
|
+
let entries;
|
|
379
|
+
try {
|
|
380
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
381
|
+
}
|
|
382
|
+
catch {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
for (const entry of entries) {
|
|
386
|
+
if (entry.isDirectory()) {
|
|
387
|
+
if (SKIP_DIRS.has(entry.name) || entry.name.startsWith('.'))
|
|
388
|
+
continue;
|
|
389
|
+
await this.walk(join(dir, entry.name), files);
|
|
390
|
+
}
|
|
391
|
+
else if (entry.isFile() && SOURCE_EXTS.has(extname(entry.name).toLowerCase())) {
|
|
392
|
+
files.push(relative(this.projectRoot, join(dir, entry.name)).replace(/\\/g, '/'));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
//# sourceMappingURL=security-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-scanner.js","sourceRoot":"","sources":["../../../src/agent/tracer/security-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity Detector — Brief'ten Entity, Relation, Endpoint Çıkarma
|
|
3
|
+
*
|
|
4
|
+
* "Todo app with users, projects, and tasks. Users can share projects."
|
|
5
|
+
* →
|
|
6
|
+
* entities: [User, Project, Task]
|
|
7
|
+
* relations: [User↔Project (many-to-many), Project→Task (one-to-many)]
|
|
8
|
+
* endpoints: [CRUD for each + share endpoint]
|
|
9
|
+
*/
|
|
10
|
+
export interface DetectedEntity {
|
|
11
|
+
name: string;
|
|
12
|
+
slug: string;
|
|
13
|
+
pluralSlug: string;
|
|
14
|
+
fields: EntityField[];
|
|
15
|
+
isAuthEntity: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface EntityField {
|
|
18
|
+
name: string;
|
|
19
|
+
type: 'string' | 'number' | 'boolean' | 'date' | 'json' | 'reference';
|
|
20
|
+
required: boolean;
|
|
21
|
+
reference?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface DetectedRelation {
|
|
24
|
+
from: string;
|
|
25
|
+
to: string;
|
|
26
|
+
type: 'one-to-many' | 'many-to-many' | 'one-to-one';
|
|
27
|
+
throughField?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface DetectedEndpoints {
|
|
30
|
+
entity: string;
|
|
31
|
+
routes: Array<{
|
|
32
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
33
|
+
path: string;
|
|
34
|
+
description: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
export interface EntityDetectionResult {
|
|
38
|
+
entities: DetectedEntity[];
|
|
39
|
+
relations: DetectedRelation[];
|
|
40
|
+
endpoints: DetectedEndpoints[];
|
|
41
|
+
}
|
|
42
|
+
export declare class EntityDetector {
|
|
43
|
+
/**
|
|
44
|
+
* Detect entities, relations, and endpoints from a brief description.
|
|
45
|
+
*/
|
|
46
|
+
detect(brief: string): EntityDetectionResult;
|
|
47
|
+
private detectRelations;
|
|
48
|
+
private generateEndpoints;
|
|
49
|
+
private matchEntityName;
|
|
50
|
+
private pluralize;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=entity-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-detector.d.ts","sourceRoot":"","sources":["../../src/orchestrator/entity-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC;IACtE,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,GAAG,cAAc,GAAG,YAAY,CAAC;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QACZ,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;QAC1C,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,SAAS,EAAE,iBAAiB,EAAE,CAAC;CAChC;AAuJD,qBAAa,cAAc;IAEzB;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,qBAAqB;IAuE5C,OAAO,CAAC,eAAe;IAmCvB,OAAO,CAAC,iBAAiB;IAqDzB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,SAAS;CAKlB"}
|