@surfinguard/core-engine 0.1.0 → 1.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.
Files changed (114) hide show
  1. package/LICENSE +21 -0
  2. package/dist/analyzers/agent-comm.d.ts +22 -0
  3. package/dist/analyzers/agent-comm.d.ts.map +1 -0
  4. package/dist/analyzers/agent-comm.js +79 -0
  5. package/dist/analyzers/agent-comm.js.map +1 -0
  6. package/dist/analyzers/api-call.d.ts +21 -0
  7. package/dist/analyzers/api-call.d.ts.map +1 -0
  8. package/dist/analyzers/api-call.js +134 -0
  9. package/dist/analyzers/api-call.js.map +1 -0
  10. package/dist/analyzers/auth.d.ts +22 -0
  11. package/dist/analyzers/auth.d.ts.map +1 -0
  12. package/dist/analyzers/auth.js +97 -0
  13. package/dist/analyzers/auth.js.map +1 -0
  14. package/dist/analyzers/code.d.ts +32 -0
  15. package/dist/analyzers/code.d.ts.map +1 -0
  16. package/dist/analyzers/code.js +310 -0
  17. package/dist/analyzers/code.js.map +1 -0
  18. package/dist/analyzers/command.d.ts.map +1 -1
  19. package/dist/analyzers/command.js +91 -39
  20. package/dist/analyzers/command.js.map +1 -1
  21. package/dist/analyzers/data-pipeline.d.ts +23 -0
  22. package/dist/analyzers/data-pipeline.d.ts.map +1 -0
  23. package/dist/analyzers/data-pipeline.js +86 -0
  24. package/dist/analyzers/data-pipeline.js.map +1 -0
  25. package/dist/analyzers/document.d.ts +22 -0
  26. package/dist/analyzers/document.d.ts.map +1 -0
  27. package/dist/analyzers/document.js +77 -0
  28. package/dist/analyzers/document.js.map +1 -0
  29. package/dist/analyzers/file-read.d.ts.map +1 -1
  30. package/dist/analyzers/file-read.js +12 -3
  31. package/dist/analyzers/file-read.js.map +1 -1
  32. package/dist/analyzers/file-write.d.ts.map +1 -1
  33. package/dist/analyzers/file-write.js +12 -3
  34. package/dist/analyzers/file-write.js.map +1 -1
  35. package/dist/analyzers/git.d.ts +25 -0
  36. package/dist/analyzers/git.d.ts.map +1 -0
  37. package/dist/analyzers/git.js +126 -0
  38. package/dist/analyzers/git.js.map +1 -0
  39. package/dist/analyzers/index.d.ts +3 -0
  40. package/dist/analyzers/index.d.ts.map +1 -1
  41. package/dist/analyzers/index.js +3 -0
  42. package/dist/analyzers/index.js.map +1 -1
  43. package/dist/analyzers/infra.d.ts +30 -0
  44. package/dist/analyzers/infra.d.ts.map +1 -0
  45. package/dist/analyzers/infra.js +134 -0
  46. package/dist/analyzers/infra.js.map +1 -0
  47. package/dist/analyzers/iot.d.ts +22 -0
  48. package/dist/analyzers/iot.d.ts.map +1 -0
  49. package/dist/analyzers/iot.js +78 -0
  50. package/dist/analyzers/iot.js.map +1 -0
  51. package/dist/analyzers/message.d.ts +22 -0
  52. package/dist/analyzers/message.d.ts.map +1 -0
  53. package/dist/analyzers/message.js +106 -0
  54. package/dist/analyzers/message.js.map +1 -0
  55. package/dist/analyzers/query.d.ts +23 -0
  56. package/dist/analyzers/query.d.ts.map +1 -0
  57. package/dist/analyzers/query.js +183 -0
  58. package/dist/analyzers/query.js.map +1 -0
  59. package/dist/analyzers/text.d.ts.map +1 -1
  60. package/dist/analyzers/text.js +20 -3
  61. package/dist/analyzers/text.js.map +1 -1
  62. package/dist/analyzers/transaction.d.ts +23 -0
  63. package/dist/analyzers/transaction.d.ts.map +1 -0
  64. package/dist/analyzers/transaction.js +100 -0
  65. package/dist/analyzers/transaction.js.map +1 -0
  66. package/dist/analyzers/ui-action.d.ts +23 -0
  67. package/dist/analyzers/ui-action.d.ts.map +1 -0
  68. package/dist/analyzers/ui-action.js +92 -0
  69. package/dist/analyzers/ui-action.js.map +1 -0
  70. package/dist/analyzers/url.d.ts.map +1 -1
  71. package/dist/analyzers/url.js +6 -2
  72. package/dist/analyzers/url.js.map +1 -1
  73. package/dist/classifier.d.ts.map +1 -1
  74. package/dist/classifier.js +20 -1
  75. package/dist/classifier.js.map +1 -1
  76. package/dist/context.d.ts +6 -4
  77. package/dist/context.d.ts.map +1 -1
  78. package/dist/context.js +34 -5
  79. package/dist/context.js.map +1 -1
  80. package/dist/engine.d.ts +72 -3
  81. package/dist/engine.d.ts.map +1 -1
  82. package/dist/engine.js +313 -9
  83. package/dist/engine.js.map +1 -1
  84. package/dist/index.d.ts +18 -1
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +17 -1
  87. package/dist/index.js.map +1 -1
  88. package/dist/patterns.d.ts +15 -1
  89. package/dist/patterns.d.ts.map +1 -1
  90. package/dist/patterns.js +70 -53
  91. package/dist/patterns.js.map +1 -1
  92. package/dist/policy-engine.d.ts +44 -0
  93. package/dist/policy-engine.d.ts.map +1 -0
  94. package/dist/policy-engine.js +225 -0
  95. package/dist/policy-engine.js.map +1 -0
  96. package/dist/session-tracker.d.ts +50 -0
  97. package/dist/session-tracker.d.ts.map +1 -0
  98. package/dist/session-tracker.js +286 -0
  99. package/dist/session-tracker.js.map +1 -0
  100. package/package.json +15 -12
  101. package/patterns/agent-comm.json +97 -0
  102. package/patterns/api-call.json +175 -0
  103. package/patterns/auth.json +116 -0
  104. package/patterns/chains.json +171 -0
  105. package/patterns/code.json +204 -0
  106. package/patterns/data-pipeline.json +116 -0
  107. package/patterns/document.json +110 -0
  108. package/patterns/git.json +118 -0
  109. package/patterns/infra.json +207 -0
  110. package/patterns/iot.json +105 -0
  111. package/patterns/message.json +122 -0
  112. package/patterns/query.json +134 -0
  113. package/patterns/transaction.json +120 -0
  114. package/patterns/ui-action.json +137 -0
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Code Analyzer — detects malicious code generation patterns.
3
+ *
4
+ * Detects 8 threat patterns (G01-G08) mapped to 5 risk primitives.
5
+ * Input: value = code string, metadata.language optional.
6
+ */
7
+ export class CodeAnalyzer {
8
+ actionType = 'code_eval';
9
+ safePatterns;
10
+ backdoorPatterns;
11
+ backdoorRegexes;
12
+ vulnerabilityPatterns;
13
+ vulnerabilityRegexes;
14
+ dependencyConfusion;
15
+ obfuscationPatterns;
16
+ obfuscationRegexes;
17
+ phoneHomeRegexes;
18
+ insecureDefaults;
19
+ insecureRegexes;
20
+ logicBombRegexes;
21
+ cryptoRegexes;
22
+ constructor(patterns) {
23
+ this.safePatterns = patterns.safePatterns.map((p) => p.toLowerCase());
24
+ this.dependencyConfusion = new Set(patterns.dependencyConfusion.map((p) => p.toLowerCase()));
25
+ // Separate regex patterns from string patterns
26
+ // Use 'is' (case-insensitive + dotAll) for multi-line code matching
27
+ this.backdoorPatterns = [];
28
+ this.backdoorRegexes = [];
29
+ for (const p of patterns.backdoorPatterns) {
30
+ if (this.isRegexPattern(p)) {
31
+ try {
32
+ this.backdoorRegexes.push(new RegExp(p, 'is'));
33
+ }
34
+ catch {
35
+ this.backdoorPatterns.push(p.toLowerCase());
36
+ }
37
+ }
38
+ else {
39
+ this.backdoorPatterns.push(p.toLowerCase());
40
+ }
41
+ }
42
+ this.vulnerabilityPatterns = [];
43
+ this.vulnerabilityRegexes = [];
44
+ for (const p of patterns.vulnerabilityPatterns) {
45
+ if (this.isRegexPattern(p)) {
46
+ try {
47
+ this.vulnerabilityRegexes.push(new RegExp(p, 'is'));
48
+ }
49
+ catch {
50
+ this.vulnerabilityPatterns.push(p.toLowerCase());
51
+ }
52
+ }
53
+ else {
54
+ this.vulnerabilityPatterns.push(p.toLowerCase());
55
+ }
56
+ }
57
+ this.obfuscationPatterns = [];
58
+ this.obfuscationRegexes = [];
59
+ for (const p of patterns.obfuscationPatterns) {
60
+ if (this.isRegexPattern(p)) {
61
+ try {
62
+ this.obfuscationRegexes.push(new RegExp(p, 'is'));
63
+ }
64
+ catch {
65
+ this.obfuscationPatterns.push(p.toLowerCase());
66
+ }
67
+ }
68
+ else {
69
+ this.obfuscationPatterns.push(p.toLowerCase());
70
+ }
71
+ }
72
+ this.phoneHomeRegexes = [];
73
+ for (const p of patterns.phoneHomePatterns) {
74
+ try {
75
+ this.phoneHomeRegexes.push(new RegExp(p, 'is'));
76
+ }
77
+ catch {
78
+ /* skip */
79
+ }
80
+ }
81
+ this.insecureDefaults = [];
82
+ this.insecureRegexes = [];
83
+ for (const p of patterns.insecureDefaults) {
84
+ if (this.isRegexPattern(p)) {
85
+ try {
86
+ this.insecureRegexes.push(new RegExp(p, 'is'));
87
+ }
88
+ catch {
89
+ this.insecureDefaults.push(p.toLowerCase());
90
+ }
91
+ }
92
+ else {
93
+ this.insecureDefaults.push(p.toLowerCase());
94
+ }
95
+ }
96
+ this.logicBombRegexes = [];
97
+ for (const p of patterns.logicBombPatterns) {
98
+ try {
99
+ this.logicBombRegexes.push(new RegExp(p, 'is'));
100
+ }
101
+ catch {
102
+ /* skip */
103
+ }
104
+ }
105
+ this.cryptoRegexes = [];
106
+ for (const p of patterns.cryptoReplacement) {
107
+ try {
108
+ this.cryptoRegexes.push(new RegExp(p, 'is'));
109
+ }
110
+ catch {
111
+ /* skip */
112
+ }
113
+ }
114
+ }
115
+ analyze(value, metadata) {
116
+ const code = value.trim();
117
+ if (!code) {
118
+ return {
119
+ actionType: 'code_eval',
120
+ findings: [],
121
+ shortCircuit: { safe: true, reason: 'Empty code' },
122
+ };
123
+ }
124
+ const lower = code.toLowerCase();
125
+ const _language = metadata?.language?.toLowerCase() ?? this.detectLanguage(code);
126
+ const findings = [];
127
+ const add = (primitive, score, reason, threatId) => {
128
+ findings.push({ primitive, score, reason, threatId });
129
+ };
130
+ // ── Safe short-circuit ──
131
+ if (code.length < 50) {
132
+ const hasRisky = this.backdoorPatterns.some((p) => lower.includes(p)) ||
133
+ this.backdoorRegexes.some((r) => r.test(code)) ||
134
+ this.vulnerabilityPatterns.some((p) => lower.includes(p)) ||
135
+ this.vulnerabilityRegexes.some((r) => r.test(code));
136
+ if (!hasRisky && this.safePatterns.some((p) => lower.includes(p))) {
137
+ return {
138
+ actionType: 'code_eval',
139
+ findings: [],
140
+ shortCircuit: { safe: true, reason: 'Short safe code' },
141
+ };
142
+ }
143
+ }
144
+ // Test file detection
145
+ if (this.isTestCode(code, lower)) {
146
+ const hasBackdoor = this.backdoorPatterns.some((p) => lower.includes(p)) ||
147
+ this.backdoorRegexes.some((r) => r.test(code));
148
+ if (!hasBackdoor) {
149
+ return {
150
+ actionType: 'code_eval',
151
+ findings: [],
152
+ shortCircuit: { safe: true, reason: 'Test code' },
153
+ };
154
+ }
155
+ }
156
+ // ── G01: Backdoor detection ──
157
+ const hasBackdoorString = this.backdoorPatterns.some((p) => lower.includes(p));
158
+ const hasBackdoorRegex = this.backdoorRegexes.some((r) => r.test(code));
159
+ if (hasBackdoorString || hasBackdoorRegex) {
160
+ add('PERSISTENCE', 10, 'Backdoor injection — reverse shell, bind shell, or socket+exec pattern', 'G01');
161
+ }
162
+ // ── G02: Vulnerability injection ──
163
+ const vulnStringHits = this.vulnerabilityPatterns.filter((p) => lower.includes(p));
164
+ const vulnRegexHits = this.vulnerabilityRegexes.some((r) => r.test(code));
165
+ // SQL string concatenation detection
166
+ const hasSqlConcat = /(?:select|insert|update|delete|drop)\b.*['"].*\+.*\+/is.test(code) ||
167
+ /(?:query|sql)\s*=\s*['"].*['"].*\+/is.test(code);
168
+ if (vulnStringHits.length > 0 || vulnRegexHits || hasSqlConcat) {
169
+ // Regex hits are always considered risky context; string hits check comments
170
+ const isRiskyContext = vulnRegexHits ||
171
+ hasSqlConcat ||
172
+ (vulnStringHits.length > 0 && !this.isCommentOrDefinition(code, vulnStringHits));
173
+ if (isRiskyContext) {
174
+ const details = hasSqlConcat
175
+ ? 'SQL string concatenation'
176
+ : vulnStringHits.join(', ') || 'dangerous function usage';
177
+ add('ESCALATION', 8, `Vulnerability injection — ${details}`, 'G02');
178
+ }
179
+ }
180
+ // ── G03: Dependency confusion ──
181
+ const importPatterns = this.extractPackageNames(code);
182
+ const suspicious = importPatterns.filter((pkg) => this.dependencyConfusion.has(pkg.toLowerCase()));
183
+ if (suspicious.length > 0) {
184
+ add('DESTRUCTION', 7, `Dependency confusion — suspicious packages: ${suspicious.join(', ')}`, 'G03');
185
+ }
186
+ // ── G04: Obfuscation ──
187
+ const hasObfuscationString = this.obfuscationPatterns.some((p) => lower.includes(p));
188
+ const hasObfuscationRegex = this.obfuscationRegexes.some((r) => r.test(code));
189
+ if (hasObfuscationString || hasObfuscationRegex) {
190
+ // Check for long encoded strings (high confidence)
191
+ const hasLongEncoded = /[A-Za-z0-9+/=]{64,}/.test(code) || /(?:\\x[0-9a-f]{2}){8,}/i.test(code);
192
+ if (hasLongEncoded) {
193
+ add('MANIPULATION', 7, 'Obfuscated code — long encoded strings detected', 'G04');
194
+ }
195
+ else {
196
+ add('MANIPULATION', 4, 'Potential obfuscation — encoding functions detected', 'G04');
197
+ }
198
+ }
199
+ // ── G05: Phone-home code ──
200
+ if (this.phoneHomeRegexes.some((r) => r.test(code))) {
201
+ add('EXFILTRATION', 8, 'Phone-home code — HTTP request combined with file/env access', 'G05');
202
+ }
203
+ else {
204
+ // Fallback: manual detection
205
+ const hasNetworkSend = /fetch|requests\.post|http\.request|urllib|axios\.post|XMLHttpRequest|curl_exec/i.test(code);
206
+ const hasDataRead = /readFile|readdir|process\.env|os\.environ|open\(/i.test(code);
207
+ if (hasNetworkSend && hasDataRead) {
208
+ add('EXFILTRATION', 7, 'Phone-home pattern — network send combined with local data access', 'G05');
209
+ }
210
+ }
211
+ // ── G06: Insecure defaults ──
212
+ const insecureStringHits = this.insecureDefaults.filter((p) => lower.includes(p));
213
+ const insecureRegexHits = this.insecureRegexes.some((r) => r.test(code));
214
+ if (insecureStringHits.length > 0 || insecureRegexHits) {
215
+ add('ESCALATION', 6, `Insecure defaults — ${insecureStringHits.join(', ') || 'hardcoded credentials or disabled security'}`, 'G06');
216
+ }
217
+ // ── G07: Logic bombs ──
218
+ if (this.logicBombRegexes.some((r) => r.test(code))) {
219
+ add('PERSISTENCE', 9, 'Logic bomb — date/condition-triggered destructive action', 'G07');
220
+ }
221
+ // ── G08: Crypto wallet replacement ──
222
+ // Check for wallet address patterns in code (regex patterns, string literals, etc.)
223
+ const hasCryptoRegex = this.cryptoRegexes.some((r) => r.test(code));
224
+ // Also detect crypto wallet patterns mentioned as regex literals or string patterns
225
+ const hasCryptoContext = /(?:bc1|0x[0-9a-f]|1[13][a-km-z])[^\s]{10,}/i.test(code) ||
226
+ /wallet.*(?:replace|address)|(?:replace|swap).*(?:wallet|btc|eth|bitcoin|0x)/is.test(code);
227
+ if (hasCryptoRegex || hasCryptoContext) {
228
+ const hasReplace = /replace|swap|substitute|overwrite/i.test(code);
229
+ const hasWalletContext = /wallet|address|btc|eth|bitcoin|ethereum|crypto/i.test(code);
230
+ if (hasReplace && hasWalletContext) {
231
+ add('EXFILTRATION', 9, 'Crypto wallet replacement — wallet address patterns with replacement logic', 'G08');
232
+ }
233
+ }
234
+ return { actionType: 'code_eval', findings };
235
+ }
236
+ isRegexPattern(pattern) {
237
+ return /[.*+?^${}()|[\]\\]/.test(pattern) && pattern !== '0.0.0.0';
238
+ }
239
+ detectLanguage(code) {
240
+ if (/^#!/.test(code) && /python|python3/.test(code))
241
+ return 'python';
242
+ if (/^#!/.test(code) && /node|deno|bun/.test(code))
243
+ return 'javascript';
244
+ if (/\bdef\s+\w+.*:$|import\s+\w+|from\s+\w+\s+import/m.test(code))
245
+ return 'python';
246
+ if (/\bfunction\s+\w+|const\s+\w+\s*=|let\s+\w+\s*=|=>\s*{/m.test(code))
247
+ return 'javascript';
248
+ if (/\bfunc\s+\w+|package\s+\w+|import\s*\(/m.test(code))
249
+ return 'go';
250
+ if (/\bfn\s+\w+|use\s+\w+::|let\s+mut\s+/m.test(code))
251
+ return 'rust';
252
+ if (/\bpublic\s+class|private\s+\w+|System\.out/m.test(code))
253
+ return 'java';
254
+ return 'unknown';
255
+ }
256
+ isTestCode(code, lower) {
257
+ const testIndicators = [
258
+ 'import unittest',
259
+ 'describe(',
260
+ 'it(',
261
+ 'test(',
262
+ 'expect(',
263
+ 'assert',
264
+ 'def test_',
265
+ '#[test]',
266
+ '@Test',
267
+ ];
268
+ return testIndicators.filter((t) => lower.includes(t.toLowerCase())).length >= 2;
269
+ }
270
+ isCommentOrDefinition(code, patterns) {
271
+ // Check if all matches are in comments or string definitions
272
+ for (const pattern of patterns) {
273
+ const lines = code.split('\n');
274
+ for (const line of lines) {
275
+ const trimmed = line.trim();
276
+ if (trimmed.toLowerCase().includes(pattern)) {
277
+ // Not a comment
278
+ if (!trimmed.startsWith('//') &&
279
+ !trimmed.startsWith('#') &&
280
+ !trimmed.startsWith('*') &&
281
+ !trimmed.startsWith('/*')) {
282
+ return false;
283
+ }
284
+ }
285
+ }
286
+ }
287
+ return true;
288
+ }
289
+ extractPackageNames(code) {
290
+ const packages = [];
291
+ // JS: require('pkg') or import ... from 'pkg'
292
+ const jsRequire = /require\s*\(\s*['"]([^'"./][^'"]*)['"]\s*\)/g;
293
+ const jsImport = /from\s+['"]([^'"./][^'"]*)['"]/g;
294
+ // Python: import pkg or from pkg import
295
+ const pyImport = /^(?:import|from)\s+([a-zA-Z_][a-zA-Z0-9_]*)/gm;
296
+ // Go: "pkg"
297
+ const goImport = /import\s+(?:\(\s*)?["']([^"']+)["']/g;
298
+ let match;
299
+ while ((match = jsRequire.exec(code)) !== null)
300
+ packages.push(match[1].split('/')[0]);
301
+ while ((match = jsImport.exec(code)) !== null)
302
+ packages.push(match[1].split('/')[0]);
303
+ while ((match = pyImport.exec(code)) !== null)
304
+ packages.push(match[1]);
305
+ while ((match = goImport.exec(code)) !== null)
306
+ packages.push(match[1]);
307
+ return packages;
308
+ }
309
+ }
310
+ //# sourceMappingURL=code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/analyzers/code.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/analyzers/command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAmB,cAAc,EAAE,MAAM,WAAW,CAAC;AAc3E;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,QAAQ,CAAC,UAAU,EAAG,SAAS,CAAU;IAEzC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;IAC5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAc;IAC9C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAc;IACrD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAc;IACtD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAc;IACjD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAc;IACjD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAc;gBAEtC,QAAQ,EAAE,sBAAsB;IAU5C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc;IAsUtC;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAqBhB;;OAEG;IACH,OAAO,CAAC,aAAa;IA0ErB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAuCvB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,wBAAwB;IAOhC,OAAO,CAAC,mBAAmB;IAe3B;;;OAGG;IACH,OAAO,CAAC,YAAY;CA6BrB"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/analyzers/command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAmB,cAAc,EAAE,MAAM,WAAW,CAAC;AAc3E;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,QAAQ,CAAC,UAAU,EAAG,SAAS,CAAU;IAEzC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;IAC5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAc;IAC9C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAc;IACrD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAc;IACtD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAc;IACjD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAc;IACjD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAc;gBAEtC,QAAQ,EAAE,sBAAsB;IAU5C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc;IAmZtC;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAqBhB;;OAEG;IACH,OAAO,CAAC,aAAa;IA0ErB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAuCvB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,gBAAgB;IAsBxB,OAAO,CAAC,wBAAwB;IAOhC,OAAO,CAAC,mBAAmB;IAe3B;;;OAGG;IACH,OAAO,CAAC,YAAY;CA6BrB"}
@@ -25,7 +25,11 @@ export class CommandAnalyzer {
25
25
  analyze(value) {
26
26
  const trimmed = value.trim();
27
27
  if (!trimmed) {
28
- return { actionType: 'command', findings: [], shortCircuit: { safe: true, reason: 'Empty command' } };
28
+ return {
29
+ actionType: 'command',
30
+ findings: [],
31
+ shortCircuit: { safe: true, reason: 'Empty command' },
32
+ };
29
33
  }
30
34
  const findings = [];
31
35
  const add = (primitive, score, reason, threatId) => {
@@ -40,7 +44,11 @@ export class CommandAnalyzer {
40
44
  if (segments.length === 1 && !hasPipe && !hasRedirect && !hasSubshell) {
41
45
  const cmd = segments[0].command.toLowerCase();
42
46
  if (this.safeCommandsSet.has(cmd) && !this.hasRiskyArgs(segments[0])) {
43
- return { actionType: 'command', findings: [], shortCircuit: { safe: true, reason: 'Known safe command' } };
47
+ return {
48
+ actionType: 'command',
49
+ findings: [],
50
+ shortCircuit: { safe: true, reason: 'Known safe command' },
51
+ };
44
52
  }
45
53
  }
46
54
  // ── 1. Pipe-to-shell (C04) ────────────────────────────────────────
@@ -78,7 +86,7 @@ export class CommandAnalyzer {
78
86
  if (this.destructiveCommandsSet.has(cmd) || this.destructiveCommandsSet.has(cmdBase)) {
79
87
  // Check for ad-hoc adjustments first
80
88
  if (cmd === 'rm') {
81
- const hasRecursive = seg.args.some(a => ['-r', '-rf', '-fr', '--recursive', '-Rf', '-fR'].includes(a));
89
+ const hasRecursive = seg.args.some((a) => ['-r', '-rf', '-fr', '--recursive', '-Rf', '-fR'].includes(a));
82
90
  const targetsCritical = this.targetsCriticalPath(seg.args);
83
91
  if (hasRecursive && targetsCritical) {
84
92
  add('DESTRUCTION', 9, `Recursive delete targeting critical path`, 'C01');
@@ -104,7 +112,7 @@ export class CommandAnalyzer {
104
112
  // Dangerous flags on non-destructive commands
105
113
  if (this.db.destructiveFlags[cmd]) {
106
114
  for (const flag of this.db.destructiveFlags[cmd]) {
107
- if (seg.args.some(a => a.includes(flag))) {
115
+ if (seg.args.some((a) => a.includes(flag))) {
108
116
  // Skip if already detected above
109
117
  if (cmd !== 'rm' && cmd !== 'dd') {
110
118
  add('DESTRUCTION', 7, `Dangerous flag ${flag} used with ${cmd}`, 'C01');
@@ -126,8 +134,8 @@ export class CommandAnalyzer {
126
134
  const cmd = seg.command.toLowerCase();
127
135
  if (cmd === 'scp' || cmd === 'rsync') {
128
136
  // scp/rsync with a remote target
129
- if (seg.args.some(a => a.includes('@') || a.includes(':'))) {
130
- if (!findings.some(f => f.threatId === 'C02')) {
137
+ if (seg.args.some((a) => a.includes('@') || a.includes(':'))) {
138
+ if (!findings.some((f) => f.threatId === 'C02')) {
131
139
  add('EXFILTRATION', 8, `${cmd} transferring data to remote host`, 'C02');
132
140
  }
133
141
  }
@@ -135,22 +143,50 @@ export class CommandAnalyzer {
135
143
  }
136
144
  // ── 8. Credential harvesting (C18) ────────────────────────────────
137
145
  const credentialPatterns = [
138
- '/etc/shadow', '/etc/passwd', '.ssh/id_rsa', '.ssh/id_ed25519',
139
- '.ssh/id_dsa', '.ssh/id_ecdsa', '.ssh/authorized_keys',
140
- '.env', '.pem', '.key', '.p12', '.pfx',
141
- 'credentials', '.aws/credentials', '.docker/config.json',
142
- '.kube/config', '.gnupg/', '.netrc',
146
+ '/etc/shadow',
147
+ '/etc/passwd',
148
+ '.ssh/id_rsa',
149
+ '.ssh/id_ed25519',
150
+ '.ssh/id_dsa',
151
+ '.ssh/id_ecdsa',
152
+ '.ssh/authorized_keys',
153
+ '.env',
154
+ '.pem',
155
+ '.key',
156
+ '.p12',
157
+ '.pfx',
158
+ 'credentials',
159
+ '.aws/credentials',
160
+ '.docker/config.json',
161
+ '.kube/config',
162
+ '.gnupg/',
163
+ '.netrc',
143
164
  ];
144
165
  for (const cred of credentialPatterns) {
145
166
  if (lower.includes(cred)) {
146
167
  // Only flag if reading, not just referencing in a safe context
147
- const isReading = segments.some(s => {
168
+ const isReading = segments.some((s) => {
148
169
  const cmd = s.command.toLowerCase();
149
- return ['cat', 'less', 'more', 'head', 'tail', 'cp', 'scp', 'rsync', 'curl', 'wget', 'base64'].includes(cmd);
170
+ return [
171
+ 'cat',
172
+ 'less',
173
+ 'more',
174
+ 'head',
175
+ 'tail',
176
+ 'cp',
177
+ 'scp',
178
+ 'rsync',
179
+ 'curl',
180
+ 'wget',
181
+ 'base64',
182
+ ].includes(cmd);
150
183
  });
151
184
  // Also flag file redirection of sensitive files
152
185
  const hasOutputRedirect = hasRedirect && lower.includes(cred);
153
- if (isReading || hasOutputRedirect || lower.includes(`-d @`) || lower.includes('--upload-file')) {
186
+ if (isReading ||
187
+ hasOutputRedirect ||
188
+ lower.includes(`-d @`) ||
189
+ lower.includes('--upload-file')) {
154
190
  add('EXFILTRATION', 8, `Accessing sensitive credential file (${cred})`, 'C18');
155
191
  break;
156
192
  }
@@ -163,8 +199,13 @@ export class CommandAnalyzer {
163
199
  if (cmd === 'sudo') {
164
200
  // sudo apt install / sudo brew install — common, reduced
165
201
  const subCmd = seg.args[0]?.toLowerCase();
166
- if (subCmd === 'apt' || subCmd === 'apt-get' || subCmd === 'brew' || subCmd === 'yum' || subCmd === 'dnf' || subCmd === 'pacman') {
167
- if (seg.args.some(a => a.toLowerCase() === 'install')) {
202
+ if (subCmd === 'apt' ||
203
+ subCmd === 'apt-get' ||
204
+ subCmd === 'brew' ||
205
+ subCmd === 'yum' ||
206
+ subCmd === 'dnf' ||
207
+ subCmd === 'pacman') {
208
+ if (seg.args.some((a) => a.toLowerCase() === 'install')) {
168
209
  add('ESCALATION', 2, `sudo ${subCmd} install — common system administration`, 'C05');
169
210
  }
170
211
  else {
@@ -186,15 +227,15 @@ export class CommandAnalyzer {
186
227
  }
187
228
  // chmod with dangerous values on critical paths
188
229
  if (cmd === 'chmod') {
189
- const hasRiskyPerm = seg.args.some(a => ['777', '000', 'a+rwx'].includes(a));
230
+ const hasRiskyPerm = seg.args.some((a) => ['777', '000', 'a+rwx'].includes(a));
190
231
  const targetsCritical = this.targetsCriticalPath(seg.args);
191
232
  if (hasRiskyPerm && targetsCritical) {
192
- if (!findings.some(f => f.threatId === 'C05' && f.score >= 8)) {
233
+ if (!findings.some((f) => f.threatId === 'C05' && f.score >= 8)) {
193
234
  add('ESCALATION', 8, `chmod with dangerous permissions on critical path`, 'C05');
194
235
  }
195
236
  }
196
237
  else if (hasRiskyPerm) {
197
- if (!findings.some(f => f.threatId === 'C05' && f.score >= 6)) {
238
+ if (!findings.some((f) => f.threatId === 'C05' && f.score >= 6)) {
198
239
  add('ESCALATION', 4, `chmod with broad permissions`, 'C05');
199
240
  }
200
241
  }
@@ -214,15 +255,15 @@ export class CommandAnalyzer {
214
255
  // ── 11. Process injection (C15) ───────────────────────────────────
215
256
  for (const seg of segments) {
216
257
  const cmd = seg.command.toLowerCase();
217
- if (cmd === 'gdb' && seg.args.some(a => a === '-p' || a === '--pid')) {
258
+ if (cmd === 'gdb' && seg.args.some((a) => a === '-p' || a === '--pid')) {
218
259
  add('ESCALATION', 8, 'Process injection via gdb attach', 'C15');
219
260
  }
220
- if (cmd === 'strace' && seg.args.some(a => a === '-p')) {
261
+ if (cmd === 'strace' && seg.args.some((a) => a === '-p')) {
221
262
  add('ESCALATION', 8, 'Process tracing via strace', 'C15');
222
263
  }
223
264
  }
224
265
  // LD_PRELOAD as inline env var (not export)
225
- if (/\bLD_PRELOAD=\S+\s+\S/.test(trimmed) && !findings.some(f => f.threatId === 'C15')) {
266
+ if (/\bLD_PRELOAD=\S+\s+\S/.test(trimmed) && !findings.some((f) => f.threatId === 'C15')) {
226
267
  add('ESCALATION', 8, 'Process injection via LD_PRELOAD', 'C15');
227
268
  }
228
269
  // ── 12. Persistence — cron (C06) ──────────────────────────────────
@@ -233,20 +274,26 @@ export class CommandAnalyzer {
233
274
  }
234
275
  }
235
276
  if (lower.includes('/etc/cron') || lower.includes('/var/spool/cron')) {
236
- if (!findings.some(f => f.threatId === 'C06')) {
277
+ if (!findings.some((f) => f.threatId === 'C06')) {
237
278
  add('PERSISTENCE', 7, 'Writing to cron directory — persistent execution', 'C06');
238
279
  }
239
280
  }
240
281
  // ── 13. Persistence — shell config (C07) ──────────────────────────
241
282
  const shellConfigs = ['.bashrc', '.zshrc', '.profile', '.bash_profile', '.bash_login'];
242
283
  for (const config of shellConfigs) {
243
- if (lower.includes(config) && (hasRedirect || lower.includes('echo') || lower.includes('tee'))) {
284
+ if (lower.includes(config) &&
285
+ (hasRedirect || lower.includes('echo') || lower.includes('tee'))) {
244
286
  add('PERSISTENCE', 6, `Modifying shell config file (${config}) — persistence`, 'C07');
245
287
  break;
246
288
  }
247
289
  }
248
290
  // ── 14. Git hook injection (C11) ──────────────────────────────────
249
- if (lower.includes('.git/hooks/') && (hasRedirect || lower.includes('echo') || lower.includes('tee') || lower.includes('cp') || lower.includes('chmod'))) {
291
+ if (lower.includes('.git/hooks/') &&
292
+ (hasRedirect ||
293
+ lower.includes('echo') ||
294
+ lower.includes('tee') ||
295
+ lower.includes('cp') ||
296
+ lower.includes('chmod'))) {
250
297
  add('PERSISTENCE', 6, 'Git hook modification — code runs on git operations', 'C11');
251
298
  }
252
299
  // ── 15. Environment poisoning (C10) ───────────────────────────────
@@ -254,7 +301,7 @@ export class CommandAnalyzer {
254
301
  add('PERSISTENCE', 6, 'PATH environment variable modification', 'C10');
255
302
  }
256
303
  if (/\bexport\s+LD_PRELOAD=/.test(trimmed)) {
257
- if (!findings.some(f => f.threatId === 'C15')) {
304
+ if (!findings.some((f) => f.threatId === 'C15')) {
258
305
  add('PERSISTENCE', 6, 'LD_PRELOAD environment variable set', 'C10');
259
306
  }
260
307
  }
@@ -280,7 +327,7 @@ export class CommandAnalyzer {
280
327
  for (const seg of segments) {
281
328
  const cmd = seg.command.toLowerCase();
282
329
  if (cmd === 'nc' || cmd === 'ncat' || cmd === 'netcat') {
283
- if (seg.args.some(a => a === '-l' || a === '-lp' || a.startsWith('-l'))) {
330
+ if (seg.args.some((a) => a === '-l' || a === '-lp' || a.startsWith('-l'))) {
284
331
  add('ESCALATION', 5, 'Network listener opened', 'C17');
285
332
  }
286
333
  }
@@ -290,14 +337,17 @@ export class CommandAnalyzer {
290
337
  }
291
338
  // python/python3 -m http.server
292
339
  if (lower.includes('http.server') || lower.includes('simplehttpserver')) {
293
- if (!findings.some(f => f.threatId === 'C17')) {
340
+ if (!findings.some((f) => f.threatId === 'C17')) {
294
341
  add('ESCALATION', 5, 'HTTP server started — exposes files on network', 'C17');
295
342
  }
296
343
  }
297
344
  // ── 18. History tampering (C12) ───────────────────────────────────
298
- if (lower.includes('history -c') || lower.includes('rm ~/.bash_history') ||
299
- lower.includes('rm -f ~/.bash_history') || lower.includes('unset histfile') ||
300
- lower.includes('export histfile=/dev/null') || lower.includes('set +o history')) {
345
+ if (lower.includes('history -c') ||
346
+ lower.includes('rm ~/.bash_history') ||
347
+ lower.includes('rm -f ~/.bash_history') ||
348
+ lower.includes('unset histfile') ||
349
+ lower.includes('export histfile=/dev/null') ||
350
+ lower.includes('set +o history')) {
301
351
  add('MANIPULATION', 4, 'Command history tampering detected', 'C12');
302
352
  }
303
353
  // ── 19. Disk filling (C16) ────────────────────────────────────────
@@ -307,7 +357,7 @@ export class CommandAnalyzer {
307
357
  // dd writing to a file (not device) — disk filling
308
358
  const hasDev = seg.raw.toLowerCase().includes('of=/dev/');
309
359
  const hasOf = seg.raw.toLowerCase().includes('of=');
310
- if (hasOf && !hasDev && !findings.some(f => f.threatId === 'C01' && f.score >= 9)) {
360
+ if (hasOf && !hasDev && !findings.some((f) => f.threatId === 'C01' && f.score >= 9)) {
311
361
  add('DESTRUCTION', 5, 'dd writing to file — potential disk filling', 'C16');
312
362
  }
313
363
  }
@@ -318,10 +368,10 @@ export class CommandAnalyzer {
318
368
  // Handle multi-word package managers like "go install"
319
369
  const fullCmd = `${cmd} ${seg.args[0] || ''}`.trim().toLowerCase();
320
370
  if (this.packageManagersSet.has(cmd) || this.packageManagersSet.has(fullCmd)) {
321
- const isInstall = seg.args.some(a => ['install', 'add', 'i'].includes(a.toLowerCase()));
371
+ const isInstall = seg.args.some((a) => ['install', 'add', 'i'].includes(a.toLowerCase()));
322
372
  if (isInstall || fullCmd.startsWith('go install')) {
323
373
  // Skip if already covered by safe commands (npm test, etc.)
324
- if (!findings.some(f => f.threatId === 'C20')) {
374
+ if (!findings.some((f) => f.threatId === 'C20')) {
325
375
  add('DESTRUCTION', 3, `Package manager install (${cmd}) — may run arbitrary scripts`, 'C20');
326
376
  }
327
377
  }
@@ -474,11 +524,13 @@ export class CommandAnalyzer {
474
524
  }
475
525
  isEncodedCommand(lower) {
476
526
  // base64 -d | bash/sh
477
- if (/base64\s+(-d|--decode)/.test(lower) && this.db.pipeToShell.some(p => lower.includes(p.toLowerCase()))) {
527
+ if (/base64\s+(-d|--decode)/.test(lower) &&
528
+ this.db.pipeToShell.some((p) => lower.includes(p.toLowerCase()))) {
478
529
  return true;
479
530
  }
480
531
  // eval $(...) with encoding
481
- if (/eval\s+\$\(/.test(lower) && (lower.includes('base64') || lower.includes('xxd') || lower.includes('echo'))) {
532
+ if (/eval\s+\$\(/.test(lower) &&
533
+ (lower.includes('base64') || lower.includes('xxd') || lower.includes('echo'))) {
482
534
  return true;
483
535
  }
484
536
  // eval "$(base64 ...)"
@@ -517,17 +569,17 @@ export class CommandAnalyzer {
517
569
  */
518
570
  hasRiskyArgs(seg) {
519
571
  const cmd = seg.command.toLowerCase();
520
- const argsLower = seg.args.map(a => a.toLowerCase());
572
+ const argsLower = seg.args.map((a) => a.toLowerCase());
521
573
  // Check if safe command is reading sensitive credentials
522
574
  if (['cat', 'less', 'more', 'head', 'tail'].includes(cmd)) {
523
575
  const credFiles = ['/etc/shadow', '.ssh/id_rsa', '.ssh/id_ed25519', '.env', '.pem', '.key'];
524
- if (seg.args.some(a => credFiles.some(c => a.toLowerCase().includes(c)))) {
576
+ if (seg.args.some((a) => credFiles.some((c) => a.toLowerCase().includes(c)))) {
525
577
  return true;
526
578
  }
527
579
  }
528
580
  // Package managers with install subcommand
529
581
  if (this.packageManagersSet.has(cmd)) {
530
- if (argsLower.some(a => ['install', 'add', 'i'].includes(a))) {
582
+ if (argsLower.some((a) => ['install', 'add', 'i'].includes(a))) {
531
583
  return true;
532
584
  }
533
585
  }