llm-mask 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/.github/workflows/llm-mask-check.yml +62 -0
- package/LICENSE +21 -0
- package/README.md +549 -0
- package/dist/audit.d.ts +56 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +90 -0
- package/dist/audit.js.map +1 -0
- package/dist/cli-old.d.ts +12 -0
- package/dist/cli-old.d.ts.map +1 -0
- package/dist/cli-old.js +257 -0
- package/dist/cli-old.js.map +1 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +197 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.d.ts +9 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +121 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +81 -0
- package/dist/config.js.map +1 -0
- package/dist/context-detection.d.ts +54 -0
- package/dist/context-detection.d.ts.map +1 -0
- package/dist/context-detection.js +219 -0
- package/dist/context-detection.js.map +1 -0
- package/dist/diff-masking.d.ts +51 -0
- package/dist/diff-masking.d.ts.map +1 -0
- package/dist/diff-masking.js +121 -0
- package/dist/diff-masking.js.map +1 -0
- package/dist/executor.d.ts +105 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +250 -0
- package/dist/executor.js.map +1 -0
- package/dist/executor.test.d.ts +5 -0
- package/dist/executor.test.d.ts.map +1 -0
- package/dist/executor.test.js +500 -0
- package/dist/executor.test.js.map +1 -0
- package/dist/features.test.d.ts +5 -0
- package/dist/features.test.d.ts.map +1 -0
- package/dist/features.test.js +118 -0
- package/dist/features.test.js.map +1 -0
- package/dist/formatter.d.ts +54 -0
- package/dist/formatter.d.ts.map +1 -0
- package/dist/formatter.js +139 -0
- package/dist/formatter.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/language-patterns.d.ts +39 -0
- package/dist/language-patterns.d.ts.map +1 -0
- package/dist/language-patterns.js +177 -0
- package/dist/language-patterns.js.map +1 -0
- package/dist/masker.d.ts +100 -0
- package/dist/masker.d.ts.map +1 -0
- package/dist/masker.js +255 -0
- package/dist/masker.js.map +1 -0
- package/dist/masker.test.d.ts +11 -0
- package/dist/masker.test.d.ts.map +1 -0
- package/dist/masker.test.js +162 -0
- package/dist/masker.test.js.map +1 -0
- package/dist/mcp-server.d.ts +9 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +494 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/patterns.d.ts +25 -0
- package/dist/patterns.d.ts.map +1 -0
- package/dist/patterns.js +184 -0
- package/dist/patterns.js.map +1 -0
- package/dist/scanner.d.ts +75 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +247 -0
- package/dist/scanner.js.map +1 -0
- package/dist/test-utils.d.ts +5 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +6 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/tokenizer.d.ts +62 -0
- package/dist/tokenizer.d.ts.map +1 -0
- package/dist/tokenizer.js +95 -0
- package/dist/tokenizer.js.map +1 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for SecureExecutor
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, mock } from 'bun:test';
|
|
5
|
+
import { SecureExecutor } from './executor.js';
|
|
6
|
+
describe('SecureExecutor', () => {
|
|
7
|
+
let executor;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
executor = new SecureExecutor();
|
|
10
|
+
});
|
|
11
|
+
describe('exec', () => {
|
|
12
|
+
it('should execute a simple command and return redacted output', async () => {
|
|
13
|
+
const result = await executor.exec({
|
|
14
|
+
command: 'echo',
|
|
15
|
+
args: ['hello world'],
|
|
16
|
+
level: 'standard'
|
|
17
|
+
});
|
|
18
|
+
expect(result.exitCode).toBe(0);
|
|
19
|
+
expect(result.stdout).toContain('hello world');
|
|
20
|
+
expect(result.signal).toBeNull();
|
|
21
|
+
expect(result.timedOut).toBe(false);
|
|
22
|
+
expect(result.redacted.stats.total).toBe(0);
|
|
23
|
+
});
|
|
24
|
+
it('should redact sensitive data in output', async () => {
|
|
25
|
+
const apiKey = 'sk-proj-abc123xyz456';
|
|
26
|
+
const result = await executor.exec({
|
|
27
|
+
command: 'echo',
|
|
28
|
+
args: [`API key is ${apiKey}`],
|
|
29
|
+
level: 'standard'
|
|
30
|
+
});
|
|
31
|
+
expect(result.stdout).toContain(apiKey);
|
|
32
|
+
expect(result.redacted.stdout).not.toContain(apiKey);
|
|
33
|
+
expect(result.redacted.stdout).toContain('[OPENAI_KEY_1]');
|
|
34
|
+
expect(result.redacted.stats.total).toBeGreaterThan(0);
|
|
35
|
+
});
|
|
36
|
+
it('should redact email addresses in output', async () => {
|
|
37
|
+
const email = 'user@example.com';
|
|
38
|
+
const result = await executor.exec({
|
|
39
|
+
command: 'echo',
|
|
40
|
+
args: [`Contact: ${email}`],
|
|
41
|
+
level: 'standard'
|
|
42
|
+
});
|
|
43
|
+
expect(result.stdout).toContain(email);
|
|
44
|
+
expect(result.redacted.stdout).not.toContain(email);
|
|
45
|
+
expect(result.redacted.stdout).toContain('[EMAIL_1]');
|
|
46
|
+
});
|
|
47
|
+
it('should preserve format when requested', async () => {
|
|
48
|
+
const email = 'user@example.com';
|
|
49
|
+
const result = await executor.exec({
|
|
50
|
+
command: 'echo',
|
|
51
|
+
args: [email],
|
|
52
|
+
level: 'standard',
|
|
53
|
+
preserveFormat: true
|
|
54
|
+
});
|
|
55
|
+
expect(result.redacted.stdout).toMatch(/u\*+@e\*+/); // j***@a*** style
|
|
56
|
+
});
|
|
57
|
+
it('should handle stderr output', async () => {
|
|
58
|
+
const result = await executor.exec({
|
|
59
|
+
command: 'sh',
|
|
60
|
+
args: ['-c', 'echo error >&2'],
|
|
61
|
+
level: 'standard'
|
|
62
|
+
});
|
|
63
|
+
expect(result.stderr).toContain('error');
|
|
64
|
+
expect(result.redacted.stderr).toContain('error');
|
|
65
|
+
});
|
|
66
|
+
it('should handle non-zero exit codes', async () => {
|
|
67
|
+
const result = await executor.exec({
|
|
68
|
+
command: 'sh',
|
|
69
|
+
args: ['-c', 'exit 42'],
|
|
70
|
+
level: 'standard'
|
|
71
|
+
});
|
|
72
|
+
expect(result.exitCode).toBe(42);
|
|
73
|
+
});
|
|
74
|
+
it('should handle command timeout', async () => {
|
|
75
|
+
const result = await executor.exec({
|
|
76
|
+
command: 'sleep',
|
|
77
|
+
args: ['100'],
|
|
78
|
+
timeout: 100,
|
|
79
|
+
level: 'standard'
|
|
80
|
+
});
|
|
81
|
+
expect(result.timedOut).toBe(true);
|
|
82
|
+
expect(result.signal).toBe('SIGTERM');
|
|
83
|
+
});
|
|
84
|
+
it('should throw error when command is missing', async () => {
|
|
85
|
+
await expect(executor.exec({
|
|
86
|
+
args: ['hello']
|
|
87
|
+
})).rejects.toThrow('Command is required');
|
|
88
|
+
});
|
|
89
|
+
it('should respect aggressive masking level', async () => {
|
|
90
|
+
const result = await executor.exec({
|
|
91
|
+
command: 'echo',
|
|
92
|
+
args: ['Call me at 555-123-4567'],
|
|
93
|
+
level: 'aggressive'
|
|
94
|
+
});
|
|
95
|
+
expect(result.redacted.stdout).toContain('[PHONE_1]');
|
|
96
|
+
expect(result.redacted.stats.total).toBeGreaterThan(0);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
describe('kubectl', () => {
|
|
100
|
+
it('should build kubectl args correctly for pod exec', async () => {
|
|
101
|
+
// Mock the exec method to avoid actual kubectl calls
|
|
102
|
+
const execSpy = mock(() => Promise.resolve({
|
|
103
|
+
stdout: 'command output',
|
|
104
|
+
stderr: '',
|
|
105
|
+
exitCode: 0,
|
|
106
|
+
signal: null,
|
|
107
|
+
timedOut: false,
|
|
108
|
+
redacted: {
|
|
109
|
+
stdout: 'command output',
|
|
110
|
+
stderr: '',
|
|
111
|
+
stats: { total: 0, byPattern: {} }
|
|
112
|
+
}
|
|
113
|
+
}));
|
|
114
|
+
executor.exec = execSpy;
|
|
115
|
+
await executor.kubectl({
|
|
116
|
+
namespace: 'production',
|
|
117
|
+
pod: 'my-pod',
|
|
118
|
+
container: 'app',
|
|
119
|
+
execCommand: 'ls /app',
|
|
120
|
+
level: 'standard'
|
|
121
|
+
});
|
|
122
|
+
const callArgs = execSpy.mock.calls[0];
|
|
123
|
+
expect(callArgs[0].command).toBe('kubectl');
|
|
124
|
+
expect(callArgs[0].args).toContain('--namespace');
|
|
125
|
+
expect(callArgs[0].args).toContain('production');
|
|
126
|
+
expect(callArgs[0].args).toContain('exec');
|
|
127
|
+
expect(callArgs[0].args).toContain('-c');
|
|
128
|
+
expect(callArgs[0].args).toContain('app');
|
|
129
|
+
expect(callArgs[0].args).toContain('my-pod');
|
|
130
|
+
});
|
|
131
|
+
it('should build kubectl args for regular commands', async () => {
|
|
132
|
+
const execSpy = mock(() => Promise.resolve({
|
|
133
|
+
stdout: 'pods listed',
|
|
134
|
+
stderr: '',
|
|
135
|
+
exitCode: 0,
|
|
136
|
+
signal: null,
|
|
137
|
+
timedOut: false,
|
|
138
|
+
redacted: {
|
|
139
|
+
stdout: 'pods listed',
|
|
140
|
+
stderr: '',
|
|
141
|
+
stats: { total: 0, byPattern: {} }
|
|
142
|
+
}
|
|
143
|
+
}));
|
|
144
|
+
executor.exec = execSpy;
|
|
145
|
+
await executor.kubectl({
|
|
146
|
+
args: ['get', 'pods'],
|
|
147
|
+
level: 'standard'
|
|
148
|
+
});
|
|
149
|
+
const callArgs = execSpy.mock.calls[0];
|
|
150
|
+
expect(callArgs[0].command).toBe('kubectl');
|
|
151
|
+
expect(callArgs[0].args).toContain('get');
|
|
152
|
+
expect(callArgs[0].args).toContain('pods');
|
|
153
|
+
});
|
|
154
|
+
it('should include context when specified', async () => {
|
|
155
|
+
const execSpy = mock(() => Promise.resolve({
|
|
156
|
+
stdout: 'output',
|
|
157
|
+
stderr: '',
|
|
158
|
+
exitCode: 0,
|
|
159
|
+
signal: null,
|
|
160
|
+
timedOut: false,
|
|
161
|
+
redacted: {
|
|
162
|
+
stdout: 'output',
|
|
163
|
+
stderr: '',
|
|
164
|
+
stats: { total: 0, byPattern: {} }
|
|
165
|
+
}
|
|
166
|
+
}));
|
|
167
|
+
executor.exec = execSpy;
|
|
168
|
+
await executor.kubectl({
|
|
169
|
+
context: 'minikube',
|
|
170
|
+
args: ['get', 'pods'],
|
|
171
|
+
level: 'standard'
|
|
172
|
+
});
|
|
173
|
+
const callArgs = execSpy.mock.calls[0];
|
|
174
|
+
expect(callArgs[0].args).toContain('--context');
|
|
175
|
+
expect(callArgs[0].args).toContain('minikube');
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
describe('ssh', () => {
|
|
179
|
+
it('should build ssh command with host', async () => {
|
|
180
|
+
const execSpy = mock(() => Promise.resolve({
|
|
181
|
+
stdout: 'remote output',
|
|
182
|
+
stderr: '',
|
|
183
|
+
exitCode: 0,
|
|
184
|
+
signal: null,
|
|
185
|
+
timedOut: false,
|
|
186
|
+
redacted: {
|
|
187
|
+
stdout: 'remote output',
|
|
188
|
+
stderr: '',
|
|
189
|
+
stats: { total: 0, byPattern: {} }
|
|
190
|
+
}
|
|
191
|
+
}));
|
|
192
|
+
executor.exec = execSpy;
|
|
193
|
+
await executor.ssh({
|
|
194
|
+
host: 'example.com',
|
|
195
|
+
remoteCommand: 'ls /tmp',
|
|
196
|
+
level: 'standard'
|
|
197
|
+
});
|
|
198
|
+
const callArgs = execSpy.mock.calls[0];
|
|
199
|
+
expect(callArgs[0].command).toBe('ssh');
|
|
200
|
+
expect(callArgs[0].args).toContain('example.com');
|
|
201
|
+
expect(callArgs[0].args).toContain('ls /tmp');
|
|
202
|
+
});
|
|
203
|
+
it('should build ssh command with user and host', async () => {
|
|
204
|
+
const execSpy = mock(() => Promise.resolve({
|
|
205
|
+
stdout: 'output',
|
|
206
|
+
stderr: '',
|
|
207
|
+
exitCode: 0,
|
|
208
|
+
signal: null,
|
|
209
|
+
timedOut: false,
|
|
210
|
+
redacted: {
|
|
211
|
+
stdout: 'output',
|
|
212
|
+
stderr: '',
|
|
213
|
+
stats: { total: 0, byPattern: {} }
|
|
214
|
+
}
|
|
215
|
+
}));
|
|
216
|
+
executor.exec = execSpy;
|
|
217
|
+
await executor.ssh({
|
|
218
|
+
host: 'example.com',
|
|
219
|
+
user: 'ubuntu',
|
|
220
|
+
remoteCommand: 'whoami',
|
|
221
|
+
level: 'standard'
|
|
222
|
+
});
|
|
223
|
+
const callArgs = execSpy.mock.calls[0];
|
|
224
|
+
expect(callArgs[0].args).toContain('ubuntu@example.com');
|
|
225
|
+
});
|
|
226
|
+
it('should include port when specified', async () => {
|
|
227
|
+
const execSpy = mock(() => Promise.resolve({
|
|
228
|
+
stdout: 'output',
|
|
229
|
+
stderr: '',
|
|
230
|
+
exitCode: 0,
|
|
231
|
+
signal: null,
|
|
232
|
+
timedOut: false,
|
|
233
|
+
redacted: {
|
|
234
|
+
stdout: 'output',
|
|
235
|
+
stderr: '',
|
|
236
|
+
stats: { total: 0, byPattern: {} }
|
|
237
|
+
}
|
|
238
|
+
}));
|
|
239
|
+
executor.exec = execSpy;
|
|
240
|
+
await executor.ssh({
|
|
241
|
+
host: 'example.com',
|
|
242
|
+
port: 2222,
|
|
243
|
+
level: 'standard'
|
|
244
|
+
});
|
|
245
|
+
const callArgs = execSpy.mock.calls[0];
|
|
246
|
+
expect(callArgs[0].args).toContain('-p');
|
|
247
|
+
expect(callArgs[0].args).toContain('2222');
|
|
248
|
+
});
|
|
249
|
+
it('should include identity file when specified', async () => {
|
|
250
|
+
const execSpy = mock(() => Promise.resolve({
|
|
251
|
+
stdout: 'output',
|
|
252
|
+
stderr: '',
|
|
253
|
+
exitCode: 0,
|
|
254
|
+
signal: null,
|
|
255
|
+
timedOut: false,
|
|
256
|
+
redacted: {
|
|
257
|
+
stdout: 'output',
|
|
258
|
+
stderr: '',
|
|
259
|
+
stats: { total: 0, byPattern: {} }
|
|
260
|
+
}
|
|
261
|
+
}));
|
|
262
|
+
executor.exec = execSpy;
|
|
263
|
+
await executor.ssh({
|
|
264
|
+
host: 'example.com',
|
|
265
|
+
identity: '~/.ssh/my_key',
|
|
266
|
+
level: 'standard'
|
|
267
|
+
});
|
|
268
|
+
const callArgs = execSpy.mock.calls[0];
|
|
269
|
+
expect(callArgs[0].args).toContain('-i');
|
|
270
|
+
expect(callArgs[0].args).toContain('~/.ssh/my_key');
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
describe('execRedacted', () => {
|
|
274
|
+
it('should return only redacted output', async () => {
|
|
275
|
+
const apiKey = 'sk-proj-abc123xyz456def789';
|
|
276
|
+
const result = await executor.execRedacted({
|
|
277
|
+
command: 'echo',
|
|
278
|
+
args: [`My key is ${apiKey}`],
|
|
279
|
+
level: 'standard'
|
|
280
|
+
});
|
|
281
|
+
// Should not contain the actual key
|
|
282
|
+
expect(result).not.toContain(apiKey);
|
|
283
|
+
// Should contain a placeholder
|
|
284
|
+
expect(result).toContain('[OPENAI_KEY_1]');
|
|
285
|
+
});
|
|
286
|
+
it('should include stderr by default', async () => {
|
|
287
|
+
const result = await executor.execRedacted({
|
|
288
|
+
command: 'sh',
|
|
289
|
+
args: ['-c', 'echo stdout; echo stderr >&2'],
|
|
290
|
+
level: 'basic'
|
|
291
|
+
});
|
|
292
|
+
expect(result).toContain('stdout');
|
|
293
|
+
expect(result).toContain('stderr');
|
|
294
|
+
});
|
|
295
|
+
it('should show exit code when requested', async () => {
|
|
296
|
+
const result = await executor.execRedacted({
|
|
297
|
+
command: 'sh',
|
|
298
|
+
args: ['-c', 'exit 42'],
|
|
299
|
+
includeExitCode: true,
|
|
300
|
+
level: 'basic'
|
|
301
|
+
});
|
|
302
|
+
expect(result).toContain('Exit code: 42');
|
|
303
|
+
});
|
|
304
|
+
it('should show timeout message', async () => {
|
|
305
|
+
const result = await executor.execRedacted({
|
|
306
|
+
command: 'sleep',
|
|
307
|
+
args: ['100'],
|
|
308
|
+
timeout: 100,
|
|
309
|
+
level: 'basic'
|
|
310
|
+
});
|
|
311
|
+
expect(result).toContain('Command timed out');
|
|
312
|
+
});
|
|
313
|
+
it('should show termination signal', async () => {
|
|
314
|
+
const result = await executor.execRedacted({
|
|
315
|
+
command: 'sh',
|
|
316
|
+
args: ['-c', 'kill $$'],
|
|
317
|
+
includeExitCode: true,
|
|
318
|
+
level: 'basic'
|
|
319
|
+
});
|
|
320
|
+
expect(result).toMatch(/Terminated by signal:/);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
describe('formatResult', () => {
|
|
324
|
+
it('should format successful result', () => {
|
|
325
|
+
const result = {
|
|
326
|
+
stdout: 'success',
|
|
327
|
+
stderr: '',
|
|
328
|
+
exitCode: 0,
|
|
329
|
+
signal: null,
|
|
330
|
+
timedOut: false,
|
|
331
|
+
redacted: {
|
|
332
|
+
stdout: 'success',
|
|
333
|
+
stderr: '',
|
|
334
|
+
stats: { total: 0, byPattern: {} }
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
const formatted = executor.formatResult(result);
|
|
338
|
+
expect(formatted).toContain('Redacted Output');
|
|
339
|
+
expect(formatted).toContain('success');
|
|
340
|
+
});
|
|
341
|
+
it('should format error result', () => {
|
|
342
|
+
const result = {
|
|
343
|
+
stdout: '',
|
|
344
|
+
stderr: 'error occurred',
|
|
345
|
+
exitCode: 1,
|
|
346
|
+
signal: null,
|
|
347
|
+
timedOut: false,
|
|
348
|
+
redacted: {
|
|
349
|
+
stdout: '',
|
|
350
|
+
stderr: 'error occurred',
|
|
351
|
+
stats: { total: 0, byPattern: {} }
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
const formatted = executor.formatResult(result);
|
|
355
|
+
expect(formatted).toContain('Exit code: 1');
|
|
356
|
+
expect(formatted).toContain('error occurred');
|
|
357
|
+
});
|
|
358
|
+
it('should format timeout result', () => {
|
|
359
|
+
const result = {
|
|
360
|
+
stdout: '',
|
|
361
|
+
stderr: '',
|
|
362
|
+
exitCode: null,
|
|
363
|
+
signal: 'SIGTERM',
|
|
364
|
+
timedOut: true,
|
|
365
|
+
redacted: {
|
|
366
|
+
stdout: '',
|
|
367
|
+
stderr: '',
|
|
368
|
+
stats: { total: 0, byPattern: {} }
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
const formatted = executor.formatResult(result);
|
|
372
|
+
expect(formatted).toContain('Command timed out');
|
|
373
|
+
expect(formatted).toContain('SIGTERM');
|
|
374
|
+
});
|
|
375
|
+
it('should show redaction count', () => {
|
|
376
|
+
const result = {
|
|
377
|
+
stdout: 'api key: sk-proj-123',
|
|
378
|
+
stderr: '',
|
|
379
|
+
exitCode: 0,
|
|
380
|
+
signal: null,
|
|
381
|
+
timedOut: false,
|
|
382
|
+
redacted: {
|
|
383
|
+
stdout: 'api key: [REDACTED]',
|
|
384
|
+
stderr: '',
|
|
385
|
+
stats: { total: 5, byPattern: { 'OPENAI_API_KEY': 5 } }
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
const formatted = executor.formatResult(result);
|
|
389
|
+
expect(formatted).toContain('Redacted 5 item(s)');
|
|
390
|
+
});
|
|
391
|
+
it('should show original output when requested', () => {
|
|
392
|
+
const result = {
|
|
393
|
+
stdout: 'sensitive data',
|
|
394
|
+
stderr: '',
|
|
395
|
+
exitCode: 0,
|
|
396
|
+
signal: null,
|
|
397
|
+
timedOut: false,
|
|
398
|
+
redacted: {
|
|
399
|
+
stdout: '[REDACTED]',
|
|
400
|
+
stderr: '',
|
|
401
|
+
stats: { total: 1, byPattern: {} }
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
const formatted = executor.formatResult(result, true);
|
|
405
|
+
expect(formatted).toContain('ORIGINAL OUTPUT');
|
|
406
|
+
expect(formatted).toContain('sensitive data');
|
|
407
|
+
expect(formatted).toContain('MAY CONTAIN SENSITIVE DATA');
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
describe('credential isolation', () => {
|
|
411
|
+
it('should mask credentials in command output while keeping them functional', async () => {
|
|
412
|
+
// This test simulates the core use case:
|
|
413
|
+
// - Credentials work for the actual command (it succeeds)
|
|
414
|
+
// - But output is redacted before LLM sees it
|
|
415
|
+
const apiKey = 'sk-proj-abc123xyz456';
|
|
416
|
+
const dbUrl = 'postgresql://user:password123@localhost:5432/mydb';
|
|
417
|
+
const sqlQuery = `SELECT * FROM users WHERE email = 'user@example.com'`;
|
|
418
|
+
// Mock a database query that returns sensitive data
|
|
419
|
+
const result = await executor.exec({
|
|
420
|
+
command: 'echo',
|
|
421
|
+
args: [
|
|
422
|
+
`Connected to DB: ${dbUrl}. Using API key: ${apiKey}. Query: ${sqlQuery}. Results: user@email.com, 555-123-4567, 192.168.1.1`
|
|
423
|
+
],
|
|
424
|
+
level: 'standard'
|
|
425
|
+
});
|
|
426
|
+
// Command succeeds (exit code 0)
|
|
427
|
+
expect(result.exitCode).toBe(0);
|
|
428
|
+
// Original output contains sensitive data
|
|
429
|
+
expect(result.stdout).toContain(apiKey);
|
|
430
|
+
expect(result.stdout).toContain('password123');
|
|
431
|
+
expect(result.stdout).toContain('user@email.com');
|
|
432
|
+
expect(result.stdout).toContain('555-123-4567');
|
|
433
|
+
expect(result.stdout).toContain('192.168.1.1');
|
|
434
|
+
// Redacted output does NOT contain sensitive data
|
|
435
|
+
expect(result.redacted.stdout).not.toContain(apiKey);
|
|
436
|
+
expect(result.redacted.stdout).not.toContain('user@email.com');
|
|
437
|
+
expect(result.redacted.stdout).not.toContain('555-123-4567');
|
|
438
|
+
expect(result.redacted.stdout).not.toContain('192.168.1.1');
|
|
439
|
+
// But still contains structure/non-sensitive parts
|
|
440
|
+
expect(result.redacted.stdout).toContain('Connected to DB');
|
|
441
|
+
expect(result.redacted.stdout).toContain('Using API key:');
|
|
442
|
+
expect(result.redacted.stdout).toContain('Query:');
|
|
443
|
+
expect(result.redacted.stdout).toContain('Results:');
|
|
444
|
+
// Stats confirm redactions occurred
|
|
445
|
+
expect(result.redacted.stats.total).toBeGreaterThan(0);
|
|
446
|
+
});
|
|
447
|
+
it('should preserve JSON structure while masking values', async () => {
|
|
448
|
+
const jsonOutput = JSON.stringify({
|
|
449
|
+
database_url: 'postgresql://user:password123@localhost:5432/db',
|
|
450
|
+
api_key: 'sk-proj-abc123xyz456',
|
|
451
|
+
admin_email: 'admin@example.com'
|
|
452
|
+
}, null, 2);
|
|
453
|
+
const result = await executor.exec({
|
|
454
|
+
command: 'echo',
|
|
455
|
+
args: [jsonOutput],
|
|
456
|
+
level: 'standard',
|
|
457
|
+
preserveFormat: false
|
|
458
|
+
});
|
|
459
|
+
// Redacted output should preserve structure but mask values
|
|
460
|
+
expect(result.redacted.stdout).toContain('{');
|
|
461
|
+
expect(result.redacted.stdout).toContain('database_url');
|
|
462
|
+
expect(result.redacted.stdout).toContain('api_key');
|
|
463
|
+
expect(result.redacted.stdout).toContain('admin_email');
|
|
464
|
+
// But actual values are redacted
|
|
465
|
+
expect(result.redacted.stdout).not.toContain('password123');
|
|
466
|
+
expect(result.redacted.stdout).not.toContain('sk-proj-abc123xyz456');
|
|
467
|
+
expect(result.redacted.stdout).not.toContain('admin@example.com');
|
|
468
|
+
});
|
|
469
|
+
it('should handle multiple sensitive patterns in one output', async () => {
|
|
470
|
+
const sensitiveOutput = `
|
|
471
|
+
Database: postgresql://user:pass123@localhost/db
|
|
472
|
+
API Key: sk-proj-abcdef123456
|
|
473
|
+
Email: user@example.com
|
|
474
|
+
Phone: 555-123-4567
|
|
475
|
+
IP: 192.168.1.1
|
|
476
|
+
Credit Card: 4532-1234-5678-9010
|
|
477
|
+
SSN: 123-45-6789
|
|
478
|
+
`;
|
|
479
|
+
const result = await executor.exec({
|
|
480
|
+
command: 'echo',
|
|
481
|
+
args: [sensitiveOutput],
|
|
482
|
+
level: 'aggressive'
|
|
483
|
+
});
|
|
484
|
+
// Count how many different patterns were redacted
|
|
485
|
+
const patternCount = Object.keys(result.redacted.stats.byPattern).length;
|
|
486
|
+
// Should have redacted multiple pattern types
|
|
487
|
+
expect(patternCount).toBeGreaterThan(3);
|
|
488
|
+
expect(result.redacted.stats.total).toBeGreaterThan(5);
|
|
489
|
+
// Verify none of the sensitive data remains
|
|
490
|
+
expect(result.redacted.stdout).not.toContain('pass123');
|
|
491
|
+
expect(result.redacted.stdout).not.toContain('sk-proj-abcdef123456');
|
|
492
|
+
expect(result.redacted.stdout).not.toContain('user@example.com');
|
|
493
|
+
expect(result.redacted.stdout).not.toContain('555-123-4567');
|
|
494
|
+
expect(result.redacted.stdout).not.toContain('192.168.1.1');
|
|
495
|
+
expect(result.redacted.stdout).not.toContain('4532-1234-5678-9010');
|
|
496
|
+
expect(result.redacted.stdout).not.toContain('123-45-6789');
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
//# sourceMappingURL=executor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.test.js","sourceRoot":"","sources":["../src/executor.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.test.d.ts","sourceRoot":"","sources":["../src/features.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for new features
|
|
3
|
+
*/
|
|
4
|
+
import { DataMasker } from './masker.js';
|
|
5
|
+
import { ContextMasker } from './context-detection.js';
|
|
6
|
+
import { Tokenizer } from './tokenizer.js';
|
|
7
|
+
import { formatEmail, formatApiKey } from './formatter.js';
|
|
8
|
+
describe('Masking Levels', () => {
|
|
9
|
+
it('should mask only API keys at basic level', () => {
|
|
10
|
+
const masker = new DataMasker();
|
|
11
|
+
const text = "Contact john@acme.com with key sk-proj-abc123xyz789";
|
|
12
|
+
const result = masker.mask(text, { level: 'basic' });
|
|
13
|
+
expect(result.masked).toContain('[OPENAI_KEY_1]');
|
|
14
|
+
expect(result.masked).toContain('john@acme.com'); // Email NOT masked at basic level
|
|
15
|
+
});
|
|
16
|
+
it('should mask PII at standard level', () => {
|
|
17
|
+
const masker = new DataMasker();
|
|
18
|
+
const text = "Contact john@acme.com with key sk-proj-abc123xyz789";
|
|
19
|
+
const result = masker.mask(text, { level: 'standard' });
|
|
20
|
+
expect(result.masked).toContain('[OPENAI_KEY_1]');
|
|
21
|
+
expect(result.masked).toContain('[EMAIL_1]');
|
|
22
|
+
});
|
|
23
|
+
it('should mask everything at aggressive level', () => {
|
|
24
|
+
const masker = new DataMasker();
|
|
25
|
+
const text = "Connecting to https://internal.api.com with user@test.com";
|
|
26
|
+
const result = masker.mask(text, { level: 'aggressive' });
|
|
27
|
+
expect(result.masked).toContain('[INTERNAL_URL_');
|
|
28
|
+
expect(result.masked).toContain('[EMAIL_');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe('Preserve Format Masking', () => {
|
|
32
|
+
it('should format email as j***@a***.com', () => {
|
|
33
|
+
const result = formatEmail('john@acme.com');
|
|
34
|
+
expect(result.formatted).toBe('j***@a***.com');
|
|
35
|
+
expect(result.original).toBe('john@acme.com');
|
|
36
|
+
});
|
|
37
|
+
it('should format API key preserving prefix', () => {
|
|
38
|
+
const result = formatApiKey('sk-proj-abc123xyz789');
|
|
39
|
+
expect(result.formatted).toContain('sk-proj-');
|
|
40
|
+
expect(result.formatted).toContain('*');
|
|
41
|
+
expect(result.original).toBe('sk-proj-abc123xyz789');
|
|
42
|
+
});
|
|
43
|
+
it('should use preserveFormat option in masker', () => {
|
|
44
|
+
const masker = new DataMasker();
|
|
45
|
+
const text = "Contact john@acme.com";
|
|
46
|
+
const result = masker.mask(text, { preserveFormat: true });
|
|
47
|
+
expect(result.masked).toContain('j***@a***.com');
|
|
48
|
+
expect(result.masked).not.toContain('[EMAIL_1]');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('Context-Aware Masking', () => {
|
|
52
|
+
it('should preserve JSON keys and mask values', () => {
|
|
53
|
+
const masker = new ContextMasker();
|
|
54
|
+
const json = '{"user": "john@acme.com", "key": "sk-proj-abc"}';
|
|
55
|
+
const result = masker.mask(json);
|
|
56
|
+
expect(result.masked).toContain('"user":');
|
|
57
|
+
expect(result.masked).not.toContain('john@acme.com');
|
|
58
|
+
expect(result.context).toBe('json');
|
|
59
|
+
});
|
|
60
|
+
it('should preserve SQL identifiers', () => {
|
|
61
|
+
const masker = new ContextMasker();
|
|
62
|
+
const sql = "SELECT * FROM users WHERE email = 'john@test.com'";
|
|
63
|
+
const result = masker.mask(sql);
|
|
64
|
+
expect(result.masked).toContain('SELECT');
|
|
65
|
+
expect(result.masked).toContain('FROM users');
|
|
66
|
+
expect(result.masked).not.toContain('john@test.com');
|
|
67
|
+
expect(result.context).toBe('sql');
|
|
68
|
+
});
|
|
69
|
+
it('should detect plaintext context', () => {
|
|
70
|
+
const masker = new ContextMasker();
|
|
71
|
+
const result = masker.mask('Just some random text');
|
|
72
|
+
expect(result.context).toBe('plaintext');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('Tokenizer', () => {
|
|
76
|
+
const salt = 'test-salt-for-tokenizer';
|
|
77
|
+
it('should tokenize consistently', () => {
|
|
78
|
+
const tokenizer = new Tokenizer({ salt });
|
|
79
|
+
const token1 = tokenizer.tokenize('secret-value');
|
|
80
|
+
const token2 = tokenizer.tokenize('secret-value');
|
|
81
|
+
expect(token1).toBe(token2);
|
|
82
|
+
expect(token1).toMatch(/^tok_[a-f0-9]{16}$/);
|
|
83
|
+
});
|
|
84
|
+
it('should tokenize differently for different values', () => {
|
|
85
|
+
const tokenizer = new Tokenizer({ salt });
|
|
86
|
+
const token1 = tokenizer.tokenize('value1');
|
|
87
|
+
const token2 = tokenizer.tokenize('value2');
|
|
88
|
+
expect(token1).not.toBe(token2);
|
|
89
|
+
});
|
|
90
|
+
it('should verify tokens correctly', () => {
|
|
91
|
+
const tokenizer = new Tokenizer({ salt });
|
|
92
|
+
const token = tokenizer.tokenize('secret');
|
|
93
|
+
expect(tokenizer.verify(token, 'secret')).toBe(true);
|
|
94
|
+
expect(tokenizer.verify(token, 'wrong')).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
it('should use context for namespacing', () => {
|
|
97
|
+
const tokenizer = new Tokenizer({ salt });
|
|
98
|
+
const token1 = tokenizer.tokenize('value', 'email');
|
|
99
|
+
const token2 = tokenizer.tokenize('value', 'api_key');
|
|
100
|
+
expect(token1).not.toBe(token2);
|
|
101
|
+
expect(token1).toContain('email_');
|
|
102
|
+
expect(token2).toContain('api_key_');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('Format Result Types', () => {
|
|
106
|
+
it('should return FormatResult for email', () => {
|
|
107
|
+
const result = formatEmail('test@example.com');
|
|
108
|
+
expect(typeof result).toBe('object');
|
|
109
|
+
expect(result).toHaveProperty('formatted');
|
|
110
|
+
expect(result).toHaveProperty('original');
|
|
111
|
+
});
|
|
112
|
+
it('should return string for SSN', () => {
|
|
113
|
+
const { formatSSN } = require('./formatter');
|
|
114
|
+
const result = formatSSN('123-45-6789');
|
|
115
|
+
expect(typeof result).toBe('string');
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
//# sourceMappingURL=features.test.js.map
|