@dotsetlabs/tollgate 0.2.2 → 0.3.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 +138 -0
- package/dist/analyzers/filesystem.d.ts +5 -0
- package/dist/analyzers/filesystem.d.ts.map +1 -1
- package/dist/analyzers/filesystem.js +61 -7
- package/dist/analyzers/filesystem.js.map +1 -1
- package/dist/analyzers/loader.d.ts +5 -0
- package/dist/analyzers/loader.d.ts.map +1 -1
- package/dist/analyzers/loader.js +112 -6
- package/dist/analyzers/loader.js.map +1 -1
- package/dist/analyzers/prompt-injection.d.ts +1 -0
- package/dist/analyzers/prompt-injection.d.ts.map +1 -1
- package/dist/analyzers/prompt-injection.js +48 -2
- package/dist/analyzers/prompt-injection.js.map +1 -1
- package/dist/analyzers/shell.d.ts +8 -0
- package/dist/analyzers/shell.d.ts.map +1 -1
- package/dist/analyzers/shell.js +109 -8
- package/dist/analyzers/shell.js.map +1 -1
- package/dist/analyzers/sql.d.ts.map +1 -1
- package/dist/analyzers/sql.js +8 -7
- package/dist/analyzers/sql.js.map +1 -1
- package/dist/approval/interactive.d.ts +1 -1
- package/dist/approval/interactive.d.ts.map +1 -1
- package/dist/approval/interactive.js +13 -1
- package/dist/approval/interactive.js.map +1 -1
- package/dist/approval/rate-limiter.d.ts +115 -0
- package/dist/approval/rate-limiter.d.ts.map +1 -0
- package/dist/approval/rate-limiter.js +200 -0
- package/dist/approval/rate-limiter.js.map +1 -0
- package/dist/approval/url-validator.d.ts +51 -0
- package/dist/approval/url-validator.d.ts.map +1 -0
- package/dist/approval/url-validator.js +184 -0
- package/dist/approval/url-validator.js.map +1 -0
- package/dist/approval/webhook.d.ts +48 -0
- package/dist/approval/webhook.d.ts.map +1 -1
- package/dist/approval/webhook.js +89 -0
- package/dist/approval/webhook.js.map +1 -1
- package/dist/audit/integrity.d.ts +107 -0
- package/dist/audit/integrity.d.ts.map +1 -0
- package/dist/audit/integrity.js +191 -0
- package/dist/audit/integrity.js.map +1 -0
- package/dist/audit/logger.d.ts.map +1 -1
- package/dist/audit/logger.js +6 -5
- package/dist/audit/logger.js.map +1 -1
- package/dist/audit/redaction.js +6 -4
- package/dist/audit/redaction.js.map +1 -1
- package/dist/cli/commands/guard.d.ts +97 -0
- package/dist/cli/commands/guard.d.ts.map +1 -0
- package/dist/cli/commands/guard.js +456 -0
- package/dist/cli/commands/guard.js.map +1 -0
- package/dist/cli/commands/serve.js +1 -1
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/index.js +3 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/input-validation.d.ts +83 -0
- package/dist/cli/input-validation.d.ts.map +1 -0
- package/dist/cli/input-validation.js +237 -0
- package/dist/cli/input-validation.js.map +1 -0
- package/dist/cli/ui.js +2 -2
- package/dist/cli/ui.js.map +1 -1
- package/dist/guard/alternatives/index.d.ts +68 -0
- package/dist/guard/alternatives/index.d.ts.map +1 -0
- package/dist/guard/alternatives/index.js +224 -0
- package/dist/guard/alternatives/index.js.map +1 -0
- package/dist/guard/alternatives/registry.d.ts +16 -0
- package/dist/guard/alternatives/registry.d.ts.map +1 -0
- package/dist/guard/alternatives/registry.js +518 -0
- package/dist/guard/alternatives/registry.js.map +1 -0
- package/dist/guard/alternatives/types.d.ts +86 -0
- package/dist/guard/alternatives/types.d.ts.map +1 -0
- package/dist/guard/alternatives/types.js +5 -0
- package/dist/guard/alternatives/types.js.map +1 -0
- package/dist/guard/approval/enhanced-terminal.d.ts +110 -0
- package/dist/guard/approval/enhanced-terminal.d.ts.map +1 -0
- package/dist/guard/approval/enhanced-terminal.js +387 -0
- package/dist/guard/approval/enhanced-terminal.js.map +1 -0
- package/dist/guard/config.d.ts +80 -0
- package/dist/guard/config.d.ts.map +1 -0
- package/dist/guard/config.js +260 -0
- package/dist/guard/config.js.map +1 -0
- package/dist/guard/context/directory.d.ts +35 -0
- package/dist/guard/context/directory.d.ts.map +1 -0
- package/dist/guard/context/directory.js +243 -0
- package/dist/guard/context/directory.js.map +1 -0
- package/dist/guard/context/environment.d.ts +31 -0
- package/dist/guard/context/environment.d.ts.map +1 -0
- package/dist/guard/context/environment.js +204 -0
- package/dist/guard/context/environment.js.map +1 -0
- package/dist/guard/context/git.d.ts +52 -0
- package/dist/guard/context/git.d.ts.map +1 -0
- package/dist/guard/context/git.js +278 -0
- package/dist/guard/context/git.js.map +1 -0
- package/dist/guard/context/index.d.ts +64 -0
- package/dist/guard/context/index.d.ts.map +1 -0
- package/dist/guard/context/index.js +227 -0
- package/dist/guard/context/index.js.map +1 -0
- package/dist/guard/context/project.d.ts +47 -0
- package/dist/guard/context/project.d.ts.map +1 -0
- package/dist/guard/context/project.js +281 -0
- package/dist/guard/context/project.js.map +1 -0
- package/dist/guard/context/types.d.ts +152 -0
- package/dist/guard/context/types.d.ts.map +1 -0
- package/dist/guard/context/types.js +7 -0
- package/dist/guard/context/types.js.map +1 -0
- package/dist/guard/engine.d.ts +107 -0
- package/dist/guard/engine.d.ts.map +1 -0
- package/dist/guard/engine.js +430 -0
- package/dist/guard/engine.js.map +1 -0
- package/dist/guard/enhanced-engine.d.ts +151 -0
- package/dist/guard/enhanced-engine.d.ts.map +1 -0
- package/dist/guard/enhanced-engine.js +622 -0
- package/dist/guard/enhanced-engine.js.map +1 -0
- package/dist/guard/hooks/index.d.ts +50 -0
- package/dist/guard/hooks/index.d.ts.map +1 -0
- package/dist/guard/hooks/index.js +325 -0
- package/dist/guard/hooks/index.js.map +1 -0
- package/dist/guard/index.d.ts +29 -0
- package/dist/guard/index.d.ts.map +1 -0
- package/dist/guard/index.js +31 -0
- package/dist/guard/index.js.map +1 -0
- package/dist/guard/learning/index.d.ts +136 -0
- package/dist/guard/learning/index.d.ts.map +1 -0
- package/dist/guard/learning/index.js +314 -0
- package/dist/guard/learning/index.js.map +1 -0
- package/dist/guard/learning/pattern-extractor.d.ts +50 -0
- package/dist/guard/learning/pattern-extractor.d.ts.map +1 -0
- package/dist/guard/learning/pattern-extractor.js +372 -0
- package/dist/guard/learning/pattern-extractor.js.map +1 -0
- package/dist/guard/learning/rule-suggester.d.ts +67 -0
- package/dist/guard/learning/rule-suggester.d.ts.map +1 -0
- package/dist/guard/learning/rule-suggester.js +345 -0
- package/dist/guard/learning/rule-suggester.js.map +1 -0
- package/dist/guard/learning/types.d.ts +211 -0
- package/dist/guard/learning/types.d.ts.map +1 -0
- package/dist/guard/learning/types.js +18 -0
- package/dist/guard/learning/types.js.map +1 -0
- package/dist/guard/preview/effects.d.ts +15 -0
- package/dist/guard/preview/effects.d.ts.map +1 -0
- package/dist/guard/preview/effects.js +413 -0
- package/dist/guard/preview/effects.js.map +1 -0
- package/dist/guard/preview/index.d.ts +49 -0
- package/dist/guard/preview/index.d.ts.map +1 -0
- package/dist/guard/preview/index.js +196 -0
- package/dist/guard/preview/index.js.map +1 -0
- package/dist/guard/preview/parser.d.ts +34 -0
- package/dist/guard/preview/parser.d.ts.map +1 -0
- package/dist/guard/preview/parser.js +292 -0
- package/dist/guard/preview/parser.js.map +1 -0
- package/dist/guard/preview/types.d.ts +140 -0
- package/dist/guard/preview/types.d.ts.map +1 -0
- package/dist/guard/preview/types.js +5 -0
- package/dist/guard/preview/types.js.map +1 -0
- package/dist/guard/reversibility/index.d.ts +88 -0
- package/dist/guard/reversibility/index.d.ts.map +1 -0
- package/dist/guard/reversibility/index.js +310 -0
- package/dist/guard/reversibility/index.js.map +1 -0
- package/dist/guard/types.d.ts +192 -0
- package/dist/guard/types.d.ts.map +1 -0
- package/dist/guard/types.js +8 -0
- package/dist/guard/types.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/orchestrator/manager.d.ts.map +1 -1
- package/dist/orchestrator/manager.js +6 -1
- package/dist/orchestrator/manager.js.map +1 -1
- package/dist/policy/engine.d.ts.map +1 -1
- package/dist/policy/engine.js +11 -3
- package/dist/policy/engine.js.map +1 -1
- package/dist/policy/parser.d.ts.map +1 -1
- package/dist/policy/parser.js +3 -0
- package/dist/policy/parser.js.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/server.js +8 -6
- package/dist/proxy/server.js.map +1 -1
- package/dist/session/manager.d.ts +2 -2
- package/dist/session/manager.d.ts.map +1 -1
- package/dist/session/manager.js +106 -88
- package/dist/session/manager.js.map +1 -1
- package/dist/session/signing.d.ts +88 -0
- package/dist/session/signing.d.ts.map +1 -0
- package/dist/session/signing.js +166 -0
- package/dist/session/signing.js.map +1 -0
- package/dist/session/types.d.ts +2 -0
- package/dist/session/types.d.ts.map +1 -1
- package/dist/session/types.js.map +1 -1
- package/dist/utils/security-logger.d.ts +146 -0
- package/dist/utils/security-logger.d.ts.map +1 -0
- package/dist/utils/security-logger.js +222 -0
- package/dist/utils/security-logger.js.map +1 -0
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +7 -1
- package/dist/wizard.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect Analyzer for Shell Guardian
|
|
3
|
+
*
|
|
4
|
+
* Analyzes what effects a command will have.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, statSync, readdirSync } from 'node:fs';
|
|
7
|
+
import { resolve, basename } from 'node:path';
|
|
8
|
+
import fg from 'fast-glob';
|
|
9
|
+
import { hasFlag } from './parser.js';
|
|
10
|
+
/**
|
|
11
|
+
* Known command effect patterns.
|
|
12
|
+
*/
|
|
13
|
+
const COMMAND_EFFECTS = {
|
|
14
|
+
// File operations
|
|
15
|
+
rm: {
|
|
16
|
+
type: 'delete',
|
|
17
|
+
targetArgs: true,
|
|
18
|
+
recursiveFlags: ['r', 'R'],
|
|
19
|
+
description: 'Delete files/directories',
|
|
20
|
+
},
|
|
21
|
+
rmdir: {
|
|
22
|
+
type: 'delete',
|
|
23
|
+
targetArgs: true,
|
|
24
|
+
description: 'Remove empty directories',
|
|
25
|
+
},
|
|
26
|
+
unlink: {
|
|
27
|
+
type: 'delete',
|
|
28
|
+
targetArgs: true,
|
|
29
|
+
description: 'Remove file',
|
|
30
|
+
},
|
|
31
|
+
// Move/Copy
|
|
32
|
+
mv: {
|
|
33
|
+
type: 'modify',
|
|
34
|
+
targetArgs: true,
|
|
35
|
+
description: 'Move/rename files',
|
|
36
|
+
},
|
|
37
|
+
cp: {
|
|
38
|
+
type: 'create',
|
|
39
|
+
targetArgs: [1], // Destination is target
|
|
40
|
+
recursiveFlags: ['r', 'R'],
|
|
41
|
+
description: 'Copy files',
|
|
42
|
+
},
|
|
43
|
+
// Create
|
|
44
|
+
touch: {
|
|
45
|
+
type: 'create',
|
|
46
|
+
targetArgs: true,
|
|
47
|
+
description: 'Create/update files',
|
|
48
|
+
},
|
|
49
|
+
mkdir: {
|
|
50
|
+
type: 'create',
|
|
51
|
+
targetArgs: true,
|
|
52
|
+
description: 'Create directories',
|
|
53
|
+
},
|
|
54
|
+
// Read
|
|
55
|
+
cat: {
|
|
56
|
+
type: 'read',
|
|
57
|
+
targetArgs: true,
|
|
58
|
+
description: 'Display file contents',
|
|
59
|
+
},
|
|
60
|
+
less: {
|
|
61
|
+
type: 'read',
|
|
62
|
+
targetArgs: true,
|
|
63
|
+
description: 'View file contents',
|
|
64
|
+
},
|
|
65
|
+
head: {
|
|
66
|
+
type: 'read',
|
|
67
|
+
targetArgs: true,
|
|
68
|
+
description: 'View start of file',
|
|
69
|
+
},
|
|
70
|
+
tail: {
|
|
71
|
+
type: 'read',
|
|
72
|
+
targetArgs: true,
|
|
73
|
+
description: 'View end of file',
|
|
74
|
+
},
|
|
75
|
+
grep: {
|
|
76
|
+
type: 'read',
|
|
77
|
+
targetArgs: true,
|
|
78
|
+
description: 'Search file contents',
|
|
79
|
+
},
|
|
80
|
+
// Permissions
|
|
81
|
+
chmod: {
|
|
82
|
+
type: 'permission',
|
|
83
|
+
targetArgs: true,
|
|
84
|
+
recursiveFlags: ['R'],
|
|
85
|
+
description: 'Change file permissions',
|
|
86
|
+
},
|
|
87
|
+
chown: {
|
|
88
|
+
type: 'permission',
|
|
89
|
+
targetArgs: true,
|
|
90
|
+
recursiveFlags: ['R'],
|
|
91
|
+
description: 'Change file ownership',
|
|
92
|
+
},
|
|
93
|
+
// Network
|
|
94
|
+
curl: {
|
|
95
|
+
type: 'network',
|
|
96
|
+
targetArgs: false,
|
|
97
|
+
description: 'HTTP request',
|
|
98
|
+
},
|
|
99
|
+
wget: {
|
|
100
|
+
type: 'network',
|
|
101
|
+
targetArgs: false,
|
|
102
|
+
description: 'Download file',
|
|
103
|
+
},
|
|
104
|
+
// Process
|
|
105
|
+
kill: {
|
|
106
|
+
type: 'process',
|
|
107
|
+
targetArgs: true,
|
|
108
|
+
description: 'Terminate process',
|
|
109
|
+
},
|
|
110
|
+
killall: {
|
|
111
|
+
type: 'process',
|
|
112
|
+
targetArgs: true,
|
|
113
|
+
description: 'Terminate processes by name',
|
|
114
|
+
},
|
|
115
|
+
pkill: {
|
|
116
|
+
type: 'process',
|
|
117
|
+
targetArgs: true,
|
|
118
|
+
description: 'Terminate processes by pattern',
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Git command effects.
|
|
123
|
+
*/
|
|
124
|
+
const GIT_EFFECTS = {
|
|
125
|
+
rm: {
|
|
126
|
+
type: 'delete',
|
|
127
|
+
targetArgs: true,
|
|
128
|
+
recursiveFlags: ['r'],
|
|
129
|
+
description: 'Remove files from git',
|
|
130
|
+
},
|
|
131
|
+
clean: {
|
|
132
|
+
type: 'delete',
|
|
133
|
+
targetArgs: false,
|
|
134
|
+
description: 'Remove untracked files',
|
|
135
|
+
},
|
|
136
|
+
checkout: {
|
|
137
|
+
type: 'modify',
|
|
138
|
+
targetArgs: true,
|
|
139
|
+
description: 'Checkout files/branches',
|
|
140
|
+
},
|
|
141
|
+
reset: {
|
|
142
|
+
type: 'modify',
|
|
143
|
+
targetArgs: true,
|
|
144
|
+
effectModifiers: { hard: 'delete' },
|
|
145
|
+
description: 'Reset state',
|
|
146
|
+
},
|
|
147
|
+
add: {
|
|
148
|
+
type: 'modify',
|
|
149
|
+
targetArgs: true,
|
|
150
|
+
description: 'Stage files',
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Default preview options.
|
|
155
|
+
*/
|
|
156
|
+
const DEFAULT_OPTIONS = {
|
|
157
|
+
maxExpandedFiles: 100,
|
|
158
|
+
maxDepth: 5,
|
|
159
|
+
expansionTimeout: 5000,
|
|
160
|
+
calculateSizes: true,
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Analyze effects of a parsed command.
|
|
164
|
+
*/
|
|
165
|
+
export async function analyzeEffects(parsed, options) {
|
|
166
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
167
|
+
const cwd = opts.cwd || process.cwd();
|
|
168
|
+
const effects = [];
|
|
169
|
+
// Get effect pattern for command
|
|
170
|
+
let effectPattern;
|
|
171
|
+
if (parsed.executable === 'git' && parsed.subcommand) {
|
|
172
|
+
effectPattern = GIT_EFFECTS[parsed.subcommand];
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
effectPattern = COMMAND_EFFECTS[parsed.executable];
|
|
176
|
+
}
|
|
177
|
+
if (!effectPattern) {
|
|
178
|
+
// Unknown command
|
|
179
|
+
effects.push({
|
|
180
|
+
type: 'unknown',
|
|
181
|
+
targets: parsed.positionalArgs,
|
|
182
|
+
confidence: 'possible',
|
|
183
|
+
description: `Unknown effect for: ${parsed.executable}`,
|
|
184
|
+
});
|
|
185
|
+
return effects;
|
|
186
|
+
}
|
|
187
|
+
// Determine targets
|
|
188
|
+
let targets = [];
|
|
189
|
+
if (effectPattern.targetArgs === true) {
|
|
190
|
+
targets = parsed.positionalArgs;
|
|
191
|
+
}
|
|
192
|
+
else if (Array.isArray(effectPattern.targetArgs)) {
|
|
193
|
+
targets = effectPattern.targetArgs
|
|
194
|
+
.filter(i => i < parsed.positionalArgs.length)
|
|
195
|
+
.map(i => parsed.positionalArgs[i]);
|
|
196
|
+
}
|
|
197
|
+
// Resolve and expand targets
|
|
198
|
+
const resolvedTargets = targets.map(t => {
|
|
199
|
+
if (t.startsWith('/'))
|
|
200
|
+
return t;
|
|
201
|
+
return resolve(cwd, t);
|
|
202
|
+
});
|
|
203
|
+
// Check for recursive flag
|
|
204
|
+
const recursive = effectPattern.recursiveFlags?.some(f => hasFlag(parsed, f)) || false;
|
|
205
|
+
// Expand globs and collect affected files
|
|
206
|
+
const expandedTargets = await expandTargets(resolvedTargets, recursive, opts);
|
|
207
|
+
// Determine actual effect type
|
|
208
|
+
let effectType = effectPattern.type;
|
|
209
|
+
if (effectPattern.effectModifiers) {
|
|
210
|
+
for (const [flag, newType] of Object.entries(effectPattern.effectModifiers)) {
|
|
211
|
+
if (hasFlag(parsed, flag)) {
|
|
212
|
+
effectType = newType;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
effects.push({
|
|
217
|
+
type: effectType,
|
|
218
|
+
targets: resolvedTargets,
|
|
219
|
+
expandedTargets: expandedTargets.files,
|
|
220
|
+
confidence: expandedTargets.truncated ? 'likely' : 'certain',
|
|
221
|
+
description: effectPattern.description,
|
|
222
|
+
recursive,
|
|
223
|
+
metadata: {
|
|
224
|
+
totalFiles: expandedTargets.total,
|
|
225
|
+
truncated: expandedTargets.truncated,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
// Check for redirects creating files
|
|
229
|
+
for (const redirect of parsed.redirects) {
|
|
230
|
+
if (redirect.type === 'stdout' || redirect.type === 'append') {
|
|
231
|
+
effects.push({
|
|
232
|
+
type: 'create',
|
|
233
|
+
targets: [redirect.target],
|
|
234
|
+
confidence: 'certain',
|
|
235
|
+
description: `${redirect.type === 'append' ? 'Append to' : 'Write to'} file`,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// Analyze piped commands
|
|
240
|
+
for (const piped of parsed.pipes) {
|
|
241
|
+
const pipedEffects = await analyzeEffects(piped, opts);
|
|
242
|
+
effects.push(...pipedEffects);
|
|
243
|
+
}
|
|
244
|
+
return effects;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Expand glob patterns and directory contents.
|
|
248
|
+
*/
|
|
249
|
+
async function expandTargets(targets, recursive, options) {
|
|
250
|
+
const files = [];
|
|
251
|
+
let total = 0;
|
|
252
|
+
let truncated = false;
|
|
253
|
+
for (const target of targets) {
|
|
254
|
+
// Check if it's a glob pattern
|
|
255
|
+
if (target.includes('*') || target.includes('?') || target.includes('[')) {
|
|
256
|
+
try {
|
|
257
|
+
const matches = await fg.glob(target, {
|
|
258
|
+
cwd: options.cwd || process.cwd(),
|
|
259
|
+
absolute: true,
|
|
260
|
+
onlyFiles: false,
|
|
261
|
+
deep: options.maxDepth,
|
|
262
|
+
});
|
|
263
|
+
total += matches.length;
|
|
264
|
+
if (files.length < options.maxExpandedFiles) {
|
|
265
|
+
const remaining = options.maxExpandedFiles - files.length;
|
|
266
|
+
files.push(...matches.slice(0, remaining));
|
|
267
|
+
if (matches.length > remaining) {
|
|
268
|
+
truncated = true;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
truncated = true;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
files.push(target);
|
|
277
|
+
total++;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
else if (existsSync(target)) {
|
|
281
|
+
const stat = statSync(target);
|
|
282
|
+
if (stat.isDirectory() && recursive) {
|
|
283
|
+
// Expand directory contents
|
|
284
|
+
try {
|
|
285
|
+
const contents = readdirSync(target, { recursive: true });
|
|
286
|
+
total += contents.length;
|
|
287
|
+
if (files.length < options.maxExpandedFiles) {
|
|
288
|
+
const remaining = options.maxExpandedFiles - files.length;
|
|
289
|
+
files.push(...contents.slice(0, remaining).map(f => resolve(target, f)));
|
|
290
|
+
if (contents.length > remaining) {
|
|
291
|
+
truncated = true;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
truncated = true;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
files.push(target);
|
|
300
|
+
total++;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
files.push(target);
|
|
305
|
+
total++;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
// Target doesn't exist yet (might be created)
|
|
310
|
+
files.push(target);
|
|
311
|
+
total++;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return { files, total, truncated };
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Calculate impact assessment from effects.
|
|
318
|
+
*/
|
|
319
|
+
export function calculateImpact(effects, options) {
|
|
320
|
+
let filesAffected = 0;
|
|
321
|
+
let directoriesAffected = 0;
|
|
322
|
+
let bytesAffected;
|
|
323
|
+
const byExtension = {};
|
|
324
|
+
const byEffectType = {};
|
|
325
|
+
let isComplete = true;
|
|
326
|
+
let incompleteReason;
|
|
327
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
328
|
+
for (const effect of effects) {
|
|
329
|
+
// Count by effect type
|
|
330
|
+
byEffectType[effect.type] = (byEffectType[effect.type] || 0) + 1;
|
|
331
|
+
const targets = effect.expandedTargets || effect.targets;
|
|
332
|
+
for (const target of targets) {
|
|
333
|
+
try {
|
|
334
|
+
if (existsSync(target)) {
|
|
335
|
+
const stat = statSync(target);
|
|
336
|
+
if (stat.isDirectory()) {
|
|
337
|
+
directoriesAffected++;
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
filesAffected++;
|
|
341
|
+
// Count by extension
|
|
342
|
+
const ext = getExtension(target);
|
|
343
|
+
byExtension[ext] = (byExtension[ext] || 0) + 1;
|
|
344
|
+
// Calculate size if requested
|
|
345
|
+
if (opts.calculateSizes) {
|
|
346
|
+
bytesAffected = (bytesAffected || 0) + stat.size;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
// Target doesn't exist (will be created or is a pattern)
|
|
352
|
+
filesAffected++;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
filesAffected++;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
// Check if results were truncated
|
|
360
|
+
if (effect.metadata?.truncated) {
|
|
361
|
+
isComplete = false;
|
|
362
|
+
incompleteReason = `Results truncated at ${opts.maxExpandedFiles} files`;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Generate summary
|
|
366
|
+
const parts = [];
|
|
367
|
+
if (filesAffected > 0) {
|
|
368
|
+
parts.push(`${filesAffected} file${filesAffected > 1 ? 's' : ''}`);
|
|
369
|
+
}
|
|
370
|
+
if (directoriesAffected > 0) {
|
|
371
|
+
parts.push(`${directoriesAffected} director${directoriesAffected > 1 ? 'ies' : 'y'}`);
|
|
372
|
+
}
|
|
373
|
+
if (bytesAffected !== undefined) {
|
|
374
|
+
parts.push(`(${formatBytes(bytesAffected)})`);
|
|
375
|
+
}
|
|
376
|
+
const summary = parts.length > 0
|
|
377
|
+
? `Affects ${parts.join(', ')}`
|
|
378
|
+
: 'No files affected';
|
|
379
|
+
return {
|
|
380
|
+
filesAffected,
|
|
381
|
+
directoriesAffected,
|
|
382
|
+
bytesAffected,
|
|
383
|
+
summary,
|
|
384
|
+
byExtension: Object.keys(byExtension).length > 0 ? byExtension : undefined,
|
|
385
|
+
byEffectType: Object.keys(byEffectType).length > 0 ? byEffectType : undefined,
|
|
386
|
+
isComplete,
|
|
387
|
+
incompleteReason,
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Get file extension.
|
|
392
|
+
*/
|
|
393
|
+
function getExtension(path) {
|
|
394
|
+
const name = basename(path);
|
|
395
|
+
const dotIndex = name.lastIndexOf('.');
|
|
396
|
+
if (dotIndex === -1 || dotIndex === 0) {
|
|
397
|
+
return '(no extension)';
|
|
398
|
+
}
|
|
399
|
+
return name.slice(dotIndex);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Format bytes to human-readable string.
|
|
403
|
+
*/
|
|
404
|
+
function formatBytes(bytes) {
|
|
405
|
+
if (bytes < 1024)
|
|
406
|
+
return `${bytes} B`;
|
|
407
|
+
if (bytes < 1024 * 1024)
|
|
408
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
409
|
+
if (bytes < 1024 * 1024 * 1024)
|
|
410
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
411
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
412
|
+
}
|
|
413
|
+
//# sourceMappingURL=effects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effects.js","sourceRoot":"","sources":["../../../src/guard/preview/effects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Preview System for Shell Guardian
|
|
3
|
+
*
|
|
4
|
+
* Generates previews of what commands will do before execution.
|
|
5
|
+
*/
|
|
6
|
+
import type { CommandPreview, PreviewOptions } from './types.js';
|
|
7
|
+
export type { CommandPreview, PreviewOptions, ParsedCommand, ParsedFlag, Redirect, CommandEffect, EffectType, EffectConfidence, ImpactAssessment, CommandEffectPattern, } from './types.js';
|
|
8
|
+
export { parseCommand, hasFlag, isRecursive, hasForceFlag, getFullCommand, getFlagValue, } from './parser.js';
|
|
9
|
+
export { analyzeEffects, calculateImpact, } from './effects.js';
|
|
10
|
+
/**
|
|
11
|
+
* Generate a preview of what a command will do.
|
|
12
|
+
*
|
|
13
|
+
* @param command - The command string
|
|
14
|
+
* @param options - Preview options
|
|
15
|
+
* @returns Command preview with effects and impact assessment
|
|
16
|
+
*/
|
|
17
|
+
export declare function generatePreview(command: string, options?: Partial<PreviewOptions>): Promise<CommandPreview>;
|
|
18
|
+
/**
|
|
19
|
+
* Format preview for terminal display.
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatPreview(preview: CommandPreview): string;
|
|
22
|
+
/**
|
|
23
|
+
* Check if preview indicates dangerous operation.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isDangerousPreview(preview: CommandPreview): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Get summary of preview for quick display.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getPreviewSummary(preview: CommandPreview): string;
|
|
30
|
+
/**
|
|
31
|
+
* PreviewGenerator class for stateful preview generation.
|
|
32
|
+
*/
|
|
33
|
+
export declare class PreviewGenerator {
|
|
34
|
+
private readonly options;
|
|
35
|
+
constructor(options?: Partial<PreviewOptions>);
|
|
36
|
+
/**
|
|
37
|
+
* Generate preview for a command.
|
|
38
|
+
*/
|
|
39
|
+
generate(command: string): Promise<CommandPreview>;
|
|
40
|
+
/**
|
|
41
|
+
* Generate quick summary without full expansion.
|
|
42
|
+
*/
|
|
43
|
+
generateQuick(command: string): Promise<string>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a preview generator.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createPreviewGenerator(options?: Partial<PreviewOptions>): PreviewGenerator;
|
|
49
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/guard/preview/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EAEf,MAAM,YAAY,CAAC;AAKpB,YAAY,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,UAAU,EACV,QAAQ,EACR,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,YAAY,EACZ,OAAO,EACP,WAAW,EACX,YAAY,EACZ,cAAc,EACd,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,eAAe,GAChB,MAAM,cAAc,CAAC;AAYtB;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,OAAO,CAAC,cAAc,CAAC,CAgCzB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CA0E7D;AAmBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAyBnE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAKjE;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;gBAE7B,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAI7C;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAIxD;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAKtD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAE1F"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Preview System for Shell Guardian
|
|
3
|
+
*
|
|
4
|
+
* Generates previews of what commands will do before execution.
|
|
5
|
+
*/
|
|
6
|
+
import { parseCommand, isRecursive } from './parser.js';
|
|
7
|
+
import { analyzeEffects, calculateImpact } from './effects.js';
|
|
8
|
+
// Re-export utilities
|
|
9
|
+
export { parseCommand, hasFlag, isRecursive, hasForceFlag, getFullCommand, getFlagValue, } from './parser.js';
|
|
10
|
+
export { analyzeEffects, calculateImpact, } from './effects.js';
|
|
11
|
+
/**
|
|
12
|
+
* Default preview options.
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_OPTIONS = {
|
|
15
|
+
maxExpandedFiles: 100,
|
|
16
|
+
maxDepth: 5,
|
|
17
|
+
expansionTimeout: 5000,
|
|
18
|
+
calculateSizes: true,
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Generate a preview of what a command will do.
|
|
22
|
+
*
|
|
23
|
+
* @param command - The command string
|
|
24
|
+
* @param options - Preview options
|
|
25
|
+
* @returns Command preview with effects and impact assessment
|
|
26
|
+
*/
|
|
27
|
+
export async function generatePreview(command, options) {
|
|
28
|
+
const startTime = Date.now();
|
|
29
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
30
|
+
const warnings = [];
|
|
31
|
+
// Parse command
|
|
32
|
+
const parsed = parseCommand(command);
|
|
33
|
+
// Analyze effects
|
|
34
|
+
let effects;
|
|
35
|
+
try {
|
|
36
|
+
effects = await analyzeEffects(parsed, opts);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
warnings.push(`Error analyzing effects: ${error}`);
|
|
40
|
+
effects = [{
|
|
41
|
+
type: 'unknown',
|
|
42
|
+
targets: parsed.positionalArgs,
|
|
43
|
+
confidence: 'possible',
|
|
44
|
+
description: 'Could not analyze command effects',
|
|
45
|
+
}];
|
|
46
|
+
}
|
|
47
|
+
// Calculate impact
|
|
48
|
+
const impact = calculateImpact(effects, opts);
|
|
49
|
+
return {
|
|
50
|
+
parsed,
|
|
51
|
+
effects,
|
|
52
|
+
impact,
|
|
53
|
+
generationTimeMs: Date.now() - startTime,
|
|
54
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Format preview for terminal display.
|
|
59
|
+
*/
|
|
60
|
+
export function formatPreview(preview) {
|
|
61
|
+
const lines = [];
|
|
62
|
+
lines.push('Command Preview');
|
|
63
|
+
lines.push('─'.repeat(50));
|
|
64
|
+
lines.push('');
|
|
65
|
+
// Command breakdown
|
|
66
|
+
lines.push(`Command: ${preview.parsed.executable}${preview.parsed.subcommand ? ' ' + preview.parsed.subcommand : ''}`);
|
|
67
|
+
if (preview.parsed.hasSudo) {
|
|
68
|
+
lines.push(' ⚠ Running with elevated privileges (sudo)');
|
|
69
|
+
}
|
|
70
|
+
if (preview.parsed.flags.length > 0) {
|
|
71
|
+
const flags = preview.parsed.flags.map(f => f.type === 'short' ? `-${f.name}` : `--${f.name}${f.value ? '=' + f.value : ''}`);
|
|
72
|
+
lines.push(` Flags: ${flags.join(' ')}`);
|
|
73
|
+
}
|
|
74
|
+
if (preview.parsed.positionalArgs.length > 0) {
|
|
75
|
+
lines.push(` Targets: ${preview.parsed.positionalArgs.join(', ')}`);
|
|
76
|
+
}
|
|
77
|
+
lines.push('');
|
|
78
|
+
// Effects
|
|
79
|
+
lines.push('Effects:');
|
|
80
|
+
for (const effect of preview.effects) {
|
|
81
|
+
const icon = getEffectIcon(effect.type);
|
|
82
|
+
const confidence = effect.confidence === 'certain' ? '' : ` (${effect.confidence})`;
|
|
83
|
+
lines.push(` ${icon} ${effect.description}${confidence}`);
|
|
84
|
+
// Show affected items
|
|
85
|
+
const targets = effect.expandedTargets || effect.targets;
|
|
86
|
+
const showCount = Math.min(5, targets.length);
|
|
87
|
+
for (let i = 0; i < showCount; i++) {
|
|
88
|
+
lines.push(` • ${targets[i]}`);
|
|
89
|
+
}
|
|
90
|
+
if (targets.length > showCount) {
|
|
91
|
+
lines.push(` ... and ${targets.length - showCount} more`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
lines.push('');
|
|
95
|
+
// Impact summary
|
|
96
|
+
lines.push('Impact:');
|
|
97
|
+
lines.push(` ${preview.impact.summary}`);
|
|
98
|
+
if (preview.impact.byExtension && Object.keys(preview.impact.byExtension).length > 0) {
|
|
99
|
+
const extSummary = Object.entries(preview.impact.byExtension)
|
|
100
|
+
.sort((a, b) => b[1] - a[1])
|
|
101
|
+
.slice(0, 5)
|
|
102
|
+
.map(([ext, count]) => `${ext}: ${count}`)
|
|
103
|
+
.join(', ');
|
|
104
|
+
lines.push(` By type: ${extSummary}`);
|
|
105
|
+
}
|
|
106
|
+
if (!preview.impact.isComplete) {
|
|
107
|
+
lines.push(` ⚠ ${preview.impact.incompleteReason}`);
|
|
108
|
+
}
|
|
109
|
+
lines.push('');
|
|
110
|
+
// Warnings
|
|
111
|
+
if (preview.warnings?.length) {
|
|
112
|
+
lines.push('Warnings:');
|
|
113
|
+
for (const warning of preview.warnings) {
|
|
114
|
+
lines.push(` ⚠ ${warning}`);
|
|
115
|
+
}
|
|
116
|
+
lines.push('');
|
|
117
|
+
}
|
|
118
|
+
return lines.join('\n');
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get icon for effect type.
|
|
122
|
+
*/
|
|
123
|
+
function getEffectIcon(type) {
|
|
124
|
+
switch (type) {
|
|
125
|
+
case 'delete': return '🗑️';
|
|
126
|
+
case 'modify': return '✏️';
|
|
127
|
+
case 'create': return '📄';
|
|
128
|
+
case 'read': return '👁️';
|
|
129
|
+
case 'execute': return '⚡';
|
|
130
|
+
case 'network': return '🌐';
|
|
131
|
+
case 'permission': return '🔒';
|
|
132
|
+
case 'process': return '⚙️';
|
|
133
|
+
default: return '❓';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if preview indicates dangerous operation.
|
|
138
|
+
*/
|
|
139
|
+
export function isDangerousPreview(preview) {
|
|
140
|
+
// Check for deletion of many files
|
|
141
|
+
if (preview.effects.some(e => e.type === 'delete' &&
|
|
142
|
+
(e.expandedTargets?.length || e.targets.length) > 10)) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
// Check for sudo delete
|
|
146
|
+
if (preview.parsed.hasSudo && preview.effects.some(e => e.type === 'delete')) {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
// Check for recursive delete
|
|
150
|
+
if (isRecursive(preview.parsed) && preview.effects.some(e => e.type === 'delete')) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
// Check for large byte impact
|
|
154
|
+
if (preview.impact.bytesAffected && preview.impact.bytesAffected > 100 * 1024 * 1024) {
|
|
155
|
+
return true; // > 100MB
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get summary of preview for quick display.
|
|
161
|
+
*/
|
|
162
|
+
export function getPreviewSummary(preview) {
|
|
163
|
+
const effectTypes = [...new Set(preview.effects.map(e => e.type))];
|
|
164
|
+
const effectSummary = effectTypes.map(t => getEffectIcon(t)).join(' ');
|
|
165
|
+
return `${effectSummary} ${preview.impact.summary}`;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* PreviewGenerator class for stateful preview generation.
|
|
169
|
+
*/
|
|
170
|
+
export class PreviewGenerator {
|
|
171
|
+
options;
|
|
172
|
+
constructor(options) {
|
|
173
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Generate preview for a command.
|
|
177
|
+
*/
|
|
178
|
+
async generate(command) {
|
|
179
|
+
return generatePreview(command, this.options);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Generate quick summary without full expansion.
|
|
183
|
+
*/
|
|
184
|
+
async generateQuick(command) {
|
|
185
|
+
const quickOpts = { ...this.options, maxExpandedFiles: 10 };
|
|
186
|
+
const preview = await generatePreview(command, quickOpts);
|
|
187
|
+
return getPreviewSummary(preview);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Create a preview generator.
|
|
192
|
+
*/
|
|
193
|
+
export function createPreviewGenerator(options) {
|
|
194
|
+
return new PreviewGenerator(options);
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=index.js.map
|