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.
Files changed (88) hide show
  1. package/.github/workflows/llm-mask-check.yml +62 -0
  2. package/LICENSE +21 -0
  3. package/README.md +549 -0
  4. package/dist/audit.d.ts +56 -0
  5. package/dist/audit.d.ts.map +1 -0
  6. package/dist/audit.js +90 -0
  7. package/dist/audit.js.map +1 -0
  8. package/dist/cli-old.d.ts +12 -0
  9. package/dist/cli-old.d.ts.map +1 -0
  10. package/dist/cli-old.js +257 -0
  11. package/dist/cli-old.js.map +1 -0
  12. package/dist/cli.d.ts +19 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +197 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/commands.d.ts +9 -0
  17. package/dist/commands.d.ts.map +1 -0
  18. package/dist/commands.js +121 -0
  19. package/dist/commands.js.map +1 -0
  20. package/dist/config.d.ts +38 -0
  21. package/dist/config.d.ts.map +1 -0
  22. package/dist/config.js +81 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/context-detection.d.ts +54 -0
  25. package/dist/context-detection.d.ts.map +1 -0
  26. package/dist/context-detection.js +219 -0
  27. package/dist/context-detection.js.map +1 -0
  28. package/dist/diff-masking.d.ts +51 -0
  29. package/dist/diff-masking.d.ts.map +1 -0
  30. package/dist/diff-masking.js +121 -0
  31. package/dist/diff-masking.js.map +1 -0
  32. package/dist/executor.d.ts +105 -0
  33. package/dist/executor.d.ts.map +1 -0
  34. package/dist/executor.js +250 -0
  35. package/dist/executor.js.map +1 -0
  36. package/dist/executor.test.d.ts +5 -0
  37. package/dist/executor.test.d.ts.map +1 -0
  38. package/dist/executor.test.js +500 -0
  39. package/dist/executor.test.js.map +1 -0
  40. package/dist/features.test.d.ts +5 -0
  41. package/dist/features.test.d.ts.map +1 -0
  42. package/dist/features.test.js +118 -0
  43. package/dist/features.test.js.map +1 -0
  44. package/dist/formatter.d.ts +54 -0
  45. package/dist/formatter.d.ts.map +1 -0
  46. package/dist/formatter.js +139 -0
  47. package/dist/formatter.js.map +1 -0
  48. package/dist/index.d.ts +36 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +37 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/language-patterns.d.ts +39 -0
  53. package/dist/language-patterns.d.ts.map +1 -0
  54. package/dist/language-patterns.js +177 -0
  55. package/dist/language-patterns.js.map +1 -0
  56. package/dist/masker.d.ts +100 -0
  57. package/dist/masker.d.ts.map +1 -0
  58. package/dist/masker.js +255 -0
  59. package/dist/masker.js.map +1 -0
  60. package/dist/masker.test.d.ts +11 -0
  61. package/dist/masker.test.d.ts.map +1 -0
  62. package/dist/masker.test.js +162 -0
  63. package/dist/masker.test.js.map +1 -0
  64. package/dist/mcp-server.d.ts +9 -0
  65. package/dist/mcp-server.d.ts.map +1 -0
  66. package/dist/mcp-server.js +494 -0
  67. package/dist/mcp-server.js.map +1 -0
  68. package/dist/patterns.d.ts +25 -0
  69. package/dist/patterns.d.ts.map +1 -0
  70. package/dist/patterns.js +184 -0
  71. package/dist/patterns.js.map +1 -0
  72. package/dist/scanner.d.ts +75 -0
  73. package/dist/scanner.d.ts.map +1 -0
  74. package/dist/scanner.js +247 -0
  75. package/dist/scanner.js.map +1 -0
  76. package/dist/test-utils.d.ts +5 -0
  77. package/dist/test-utils.d.ts.map +1 -0
  78. package/dist/test-utils.js +6 -0
  79. package/dist/test-utils.js.map +1 -0
  80. package/dist/tokenizer.d.ts +62 -0
  81. package/dist/tokenizer.d.ts.map +1 -0
  82. package/dist/tokenizer.js +95 -0
  83. package/dist/tokenizer.js.map +1 -0
  84. package/dist/types.d.ts +63 -0
  85. package/dist/types.d.ts.map +1 -0
  86. package/dist/types.js +16 -0
  87. package/dist/types.js.map +1 -0
  88. package/package.json +60 -0
@@ -0,0 +1,62 @@
1
+ name: llm-mask - Check for Leaked Secrets
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main, develop]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ llm-mask-scan:
12
+ name: Scan for secrets
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Checkout code
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Setup Node.js
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: '20'
22
+
23
+ - name: Install llm-mask
24
+ run: |
25
+ npm install -g llm-mask
26
+ # Or build from local source if in same repo
27
+ # npm install && npm run build
28
+
29
+ - name: Scan codebase
30
+ id: scan
31
+ continue-on-error: true
32
+ run: |
33
+ npx llm-mask scan . --fail-on-detect --level basic \
34
+ --extensions .ts,.js,.py,.go,.rs,.java,.env,.yaml,.yml,.json \
35
+ --skip-dir node_modules,dist,build,.git,target \
36
+ 2>&1 | tee scan-output.txt
37
+
38
+ - name: Upload scan results
39
+ if: always()
40
+ uses: actions/upload-artifact@v4
41
+ with:
42
+ name: llm-mask-scan-results
43
+ path: scan-output.txt
44
+ retention-days: 30
45
+
46
+ - name: Comment on PR
47
+ if: github.event_name == 'pull_request' && steps.scan.outcome == 'failure'
48
+ uses: actions/github-script@v7
49
+ with:
50
+ script: |
51
+ const fs = require('fs');
52
+ const output = fs.readFileSync('scan-output.txt', 'utf8');
53
+ github.rest.issues.createComment({
54
+ issue_number: context.issue.number,
55
+ owner: context.repo.owner,
56
+ repo: context.repo.repo,
57
+ body: `## 🔐 llm-mask Scan Results\n\n${output}\n\nPlease review and remove any sensitive data before merging.`
58
+ });
59
+
60
+ - name: Fail if secrets found
61
+ if: steps.scan.outcome == 'failure'
62
+ run: exit 1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dolphy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,549 @@
1
+ # llm-mask
2
+
3
+ > Mask sensitive data before sending to LLMs. Keep the semantic meaning, lose the secrets.
4
+
5
+ **Version 0.3.0** - Now with exec/kube/ssh commands for credential isolation.
6
+
7
+ ## Features
8
+
9
+ ✅ **23 Built-in Patterns** - API keys, emails, IPs, PII, URLs, UUIDs, hashes, file paths
10
+ ✅ **Credential Isolation** - Execute commands with real credentials, output redacted for LLMs
11
+ ✅ **Kubernetes Support** - Run kubectl commands safely with automatic redaction
12
+ ✅ **SSH Support** - Execute remote commands without exposing credentials
13
+ ✅ **Masking Levels** - basic (secrets), standard (+PII), aggressive (everything)
14
+ ✅ **Preserve Format** - `j***@a***.com` instead of `[EMAIL_1]`
15
+ ✅ **Custom Patterns** - Define your own via config file
16
+ ✅ **Scan Codebases** - Find secrets in entire projects
17
+ ✅ **Diff Masking** - Safe git diff for LLM code review
18
+ ✅ **Context Detection** - Smart masking for SQL, JSON, YAML
19
+ ✅ **Language Patterns** - Python, JavaScript, Go, Ruby, Terraform
20
+ ✅ **Reversible Tokenization** - Deterministic encryption with salt
21
+ ✅ **Audit Logging** - Safe logging without actual values
22
+ ✅ **CI/CD Integration** - GitHub Actions workflow included
23
+
24
+ ## Quick Start
25
+
26
+ ```bash
27
+ npm install -g llm-mask
28
+ ```
29
+
30
+ ### Basic Usage
31
+
32
+ ```bash
33
+ # Mask sensitive data
34
+ echo "API key sk-proj-abc123 expired for john@acme.com" | llm-mask
35
+
36
+ # Preserve format for readability
37
+ llm-mask --preserve-format "Contact john@acme.com"
38
+
39
+ # Mask only secrets (not emails)
40
+ llm-mask --level basic "Contact john@acme.com with key sk-abc123"
41
+
42
+ # Scan codebase for secrets
43
+ llm-mask scan ./src
44
+
45
+ # Mask git diff for safe code review
46
+ git diff main | llm-mask diff
47
+
48
+ # Context-aware masking (preserves structure)
49
+ llm-mask --context '{"user": "john@acme.com", "key": "sk-abc123"}'
50
+
51
+ # Execute commands with credential isolation
52
+ llm-mask exec kubectl get secrets -n production
53
+ llm-mask kube -n production get secrets
54
+ llm-mask ssh user@server "cat /etc/secrets/db.conf"
55
+ ```
56
+
57
+ ## Credential Isolation (NEW!)
58
+
59
+ The core principle: **Credentials work for the command, but output is redacted before the LLM sees it.**
60
+
61
+ ### Exec Command
62
+
63
+ Run any command and automatically redact sensitive output:
64
+
65
+ ```bash
66
+ # Show environment variables without exposing actual values
67
+ llm-mask exec env | grep -i key
68
+
69
+ # Run database queries safely
70
+ llm-mask exec psql -c "SELECT * FROM users"
71
+
72
+ # Check AWS credentials without revealing them
73
+ llm-mask exec aws sts get-caller-identity
74
+ ```
75
+
76
+ ### Kubernetes Command
77
+
78
+ Execute kubectl commands with automatic redaction:
79
+
80
+ ```bash
81
+ # List secrets (values are masked)
82
+ llm-mask kube -n production get secrets
83
+
84
+ # Execute into a pod and run commands
85
+ llm-mask kube -n production --pod my-app --exec "env | grep -i password"
86
+
87
+ # Get config with credentials masked
88
+ llm-mask kube -n staging config
89
+
90
+ # Full kubectl command passthrough with redaction
91
+ llm-mask kube --context minikube get pods -o yaml
92
+ ```
93
+
94
+ ### SSH Command
95
+
96
+ Execute commands on remote servers without exposing credentials in LLM context:
97
+
98
+ ```bash
99
+ # Execute remote command with redacted output
100
+ llm-mask ssh user@production-server "cat /etc/secrets/app.conf"
101
+
102
+ # With custom port and identity
103
+ llm-mask ssh -p 2222 -i ~/.ssh/deploy_key deploy@server "systemctl status"
104
+
105
+ # Interactive mode (for debugging, output is still redacted)
106
+ llm-mask ssh user@test-server
107
+ ```
108
+
109
+ ### Example Use Case
110
+
111
+ Debugging a Kubernetes issue with an LLM:
112
+
113
+ ```bash
114
+ # Without llm-mask - DANGER!
115
+ kubectl get secrets -n production
116
+ # Output: password=SuperSecret123, api_key=sk-proj-abc123
117
+
118
+ # With llm-mask - SAFE!
119
+ llm-mask kube -n production get secrets
120
+ # Output: password=[CREDENTIALS_1], api_key=[OPENAI_KEY_1]
121
+ # 🔒 Redacted 2 item(s)
122
+
123
+ # Now you can share this with an LLM for debugging
124
+ # without leaking actual credentials!
125
+ ```
126
+
127
+ ## Features Deep Dive
128
+
129
+ ### 1. Masking Levels
130
+
131
+ Control what gets masked:
132
+
133
+ ```bash
134
+ --level basic # Only API keys/secrets (priority 90+)
135
+ --level standard # + PII like emails, phones (priority 40+) [default]
136
+ --level aggressive # Everything including URLs, file paths
137
+ ```
138
+
139
+ ### 2. Preserve Format
140
+
141
+ Keep structure visible while protecting values:
142
+
143
+ ```bash
144
+ $ llm-mask --preserve-format "Email: john@acme.com"
145
+ Email: j***@a***.com
146
+
147
+ $ llm-mask --preserve-format "Card: 4111 1111 1111 1111"
148
+ Card: 4111 ************ 1111
149
+ ```
150
+
151
+ ### 3. Custom Patterns File
152
+
153
+ Create `.llm-mask-rules.json` in your project:
154
+
155
+ ```json
156
+ {
157
+ "customPatterns": [
158
+ {
159
+ "name": "employee_id",
160
+ "regex": "\\bEMP-[0-9]{6}\\b",
161
+ "placeholder": "[EMPLOYEE_ID_{i}]"
162
+ },
163
+ {
164
+ "name": "internal_ticket",
165
+ "regex": "\\bTICKET-[A-Z]{3}-[0-9]{4}\\b",
166
+ "placeholder": "[TICKET_{i}]"
167
+ }
168
+ ],
169
+ "defaultLevel": "standard",
170
+ "auditLog": true
171
+ }
172
+ ```
173
+
174
+ ### 4. Scan & Report
175
+
176
+ Scan entire codebases for leaked secrets:
177
+
178
+ ```bash
179
+ $ llm-mask scan ./src
180
+
181
+ 🔍 llm-mask Scan Report
182
+
183
+ Scanned: 47 files
184
+ Skipped: 123 files
185
+ Findings: 3 sensitive pattern(s)
186
+
187
+ ⚠️ Findings:
188
+
189
+ config.ts:
190
+ ❌ Line 15: openai_api_key
191
+ const apiKey = "sk-proj-abc123xyz789abcdef123"
192
+
193
+ .env.example:
194
+ ⚠️ Line 8: email
195
+ support@example.com
196
+
197
+ db.ts:
198
+ ❌ Line 42: url_with_creds
199
+ postgresql://admin:password@localhost/db
200
+ ```
201
+
202
+ ### 5. Diff Masking
203
+
204
+ Safe code review with LLMs:
205
+
206
+ ```bash
207
+ # Mask git diff output
208
+ git diff main | llm-mask diff
209
+
210
+ # Or use the diff mode directly
211
+ llm-mask diff --base main --head feature-branch
212
+ ```
213
+
214
+ ### 6. Context Detection
215
+
216
+ Smart masking that preserves structure:
217
+
218
+ ```bash
219
+ # JSON - preserves keys, masks values
220
+ $ llm-mask --context '{"email": "john@test.com"}'
221
+ {"email": "[EMAIL_1]"}
222
+
223
+ # SQL - preserves identifiers, masks literals
224
+ $ llm-mask --context "SELECT * FROM users WHERE email = 'john@test.com'"
225
+ SELECT * FROM users WHERE email = '[EMAIL_1]'
226
+
227
+ # YAML - preserves keys, masks values
228
+ $ llm-mask --context "api_key: sk-proj-abc123"
229
+ api_key: [OPENAI_KEY_1]
230
+ ```
231
+
232
+ ### 7. Language-Specific Patterns
233
+
234
+ Automatically detects and masks language-specific patterns:
235
+
236
+ | Language | Patterns |
237
+ |----------|----------|
238
+ | Python | Django SECRET_KEY, SQLAlchemy URLs, boto3 keys |
239
+ | JavaScript/TypeScript | Firebase configs, JWT tokens, MongoDB URIs |
240
+ | Go | AWS SDK configs, env structs |
241
+ | Ruby | Rails secret_key_base, DB passwords |
242
+ | Terraform | AWS access/secret keys |
243
+
244
+ ### 8. Reversible Tokenization
245
+
246
+ For production use with deterministic encryption:
247
+
248
+ ```typescript
249
+ import { Tokenizer } from 'llm-mask'
250
+
251
+ const tokenizer = new Tokenizer({
252
+ salt: 'your-secure-salt-here' // Generate with: llm-tokenizer-generate-salt
253
+ })
254
+
255
+ // Tokenize (deterministic - same input = same output)
256
+ const token = tokenizer.tokenize('john@test.com')
257
+ // Returns: "tok_a1b2c3d4e5f6g7h8"
258
+
259
+ // Verify without storing mappings
260
+ tokenizer.verify(token, 'john@test.com') // true
261
+ tokenizer.verify(token, 'wrong@email.com') // false
262
+ ```
263
+
264
+ ### 9. Audit Logging
265
+
266
+ Safe logging without sensitive values:
267
+
268
+ ```typescript
269
+ import { AuditLogger } from 'llm-mask'
270
+
271
+ const logger = new AuditLogger({
272
+ file: './audit.log',
273
+ console: true
274
+ })
275
+
276
+ logger.log({
277
+ timestamp: 1234567890,
278
+ patternName: 'email',
279
+ placeholder: '[EMAIL_1]',
280
+ inputLength: 123,
281
+ context: 'user-registration'
282
+ })
283
+ ```
284
+
285
+ ### 10. CI/CD Integration
286
+
287
+ GitHub Actions workflow included:
288
+
289
+ ```yaml
290
+ # .github/workflows/llm-mask-check.yml
291
+ name: llm-mask - Check for Leaked Secrets
292
+ on: [push, pull_request]
293
+ jobs:
294
+ scan:
295
+ runs-on: ubuntu-latest
296
+ steps:
297
+ - uses: actions/checkout@v4
298
+ - run: npx llm-mask scan . --fail-on-detect
299
+ ```
300
+
301
+ ## CLI Options
302
+
303
+ ```
304
+ Usage: llm-mask [options] [text]
305
+
306
+ Options:
307
+ --check, -c Dry run: show what would be masked
308
+ --level, -l Masking level (basic|standard|aggressive)
309
+ --preserve-format, -f Preserve format (j***@a***.com)
310
+ --context Smart context detection (SQL, JSON, etc.)
311
+ --unmask, -u Unmask previously masked text
312
+ --patterns, -p List all available patterns
313
+ --json, -j Output as JSON
314
+ --config <path> Path to config file
315
+
316
+ Commands:
317
+ exec [command...] Execute command with output redaction
318
+ kube [kubectl-args] Execute kubectl with output redaction
319
+ ssh <host> Execute SSH command with output redaction
320
+ scan [path] Scan codebase for secrets
321
+ diff Mask git diff output
322
+ patterns List all available patterns
323
+
324
+ Examples:
325
+ # Pipe mode
326
+ echo "API key sk-proj-123" | llm-mask
327
+
328
+ # Exec commands
329
+ llm-mask exec env | grep -i key
330
+ llm-mask kube -n production get secrets
331
+ llm-mask ssh user@server "cat /etc/secrets/app.conf"
332
+
333
+ # Scan codebase
334
+ llm-mask scan ./src --fail-on-detect
335
+
336
+ # Git diff
337
+ git diff main | llm-mask diff
338
+
339
+ # Preserve format
340
+ llm-mask --preserve-format "Contact john@acme.com"
341
+ ```
342
+
343
+ ## Built-in Patterns
344
+
345
+ | Category | Patterns | Example |
346
+ |----------|----------|---------|
347
+ | API Keys | OpenAI, Anthropic, Stripe, AWS, GitHub, JWT | `[OPENAI_KEY_1]` |
348
+ | PII | Emails, SSNs, Credit Cards, Phones | `[EMAIL_1]` |
349
+ | URLs | URLs with credentials, internal URLs | `[CREDENTIALS_1]@` |
350
+ | Network | IPv4, IPv6 | `[IP_1]` |
351
+ | Identifiers | UUIDs, SHA256, MD5 hashes | `[UUID_1]` |
352
+ | Files | Unix paths, Windows paths | `[PATH_1]` |
353
+
354
+ ## MCP Server
355
+
356
+ Add to Claude Code settings.json:
357
+
358
+ ```json
359
+ {
360
+ "mcpServers": {
361
+ "llm-mask": {
362
+ "command": "node",
363
+ "args": ["/path/to/llm-mask/dist/mcp-server.js"]
364
+ }
365
+ }
366
+ }
367
+ ```
368
+
369
+ Available tools:
370
+ - `mask_data` - Mask text with options
371
+ - `unmask_data` - Unmask (trusted only)
372
+ - `check_masking` - Dry run
373
+ - `scan_directory` - Scan codebase
374
+ - `mask_diff` - Mask git diff
375
+ - `mask_context` - Context-aware masking
376
+ - `list_patterns` - List patterns
377
+ - `clear_mappings` - Clear memory
378
+ - `exec_redacted` - Execute command with output redaction (NEW!)
379
+ - `kube_exec` - Execute kubectl with redaction (NEW!)
380
+ - `ssh_exec` - Execute SSH command with redaction (NEW!)
381
+
382
+ ## Security & Data Protection
383
+
384
+ ### How It Works
385
+
386
+ ```
387
+ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
388
+ │ Claude │ asks │ llm-mask │ sends │ LLM API │
389
+ │ Code │────────▶│ MCP Server │────────▶│ (Claude) │
390
+ │ (Local) │ │ (Local) │ │ (Remote) │
391
+ └─────────────┘ └─────────────┘ └─────────────┘
392
+ │ │ │
393
+ │ │ masked data │
394
+ │ │ only │
395
+ └───────────────────────┴────────────────────────┘
396
+ Your sensitive data NEVER leaves your machine
397
+ ```
398
+
399
+ **The key insight**: llm-mask runs **locally on your machine**. The MCP server:
400
+ 1. Receives requests from Claude Code
401
+ 2. Masks the data **before** anything leaves your machine
402
+ 3. Sends only masked data to the LLM
403
+
404
+ ### What is Protected ✅
405
+
406
+ | Scenario | Protected? | How |
407
+ |----------|-----------|-----|
408
+ | Explicit masking via MCP tools | ✅ Yes | Data masked locally before sending |
409
+ | Using `exec_redacted` tool | ✅ Yes | Command runs locally, output masked before LLM sees it |
410
+ | Using `kube_exec` tool | ✅ Yes | Credentials work for kubectl, output is masked |
411
+ | Using `ssh_exec` tool | ✅ Yes | Credentials work for SSH, output is masked |
412
+
413
+ ### What is NOT Protected ⚠️
414
+
415
+ | Scenario | Risk | Why |
416
+ |----------|------|-----|
417
+ | You paste sensitive data directly in chat | ❌ Not protected | Goes straight to LLM without masking |
418
+ | You share file contents without masking | ❌ Not protected | File content sent directly to LLM |
419
+ | Claude Code reads files independently | ❌ Not protected | MCP doesn't intercept file reads |
420
+
421
+ ### Example Usage
422
+
423
+ ```typescript
424
+ // ❌ BAD - Pasting directly (NOT protected)
425
+ User: "Help me debug this error with API key sk-proj-abc123"
426
+ // → The key goes directly to Claude's API
427
+
428
+ // ✅ GOOD - Using MCP tool (protected)
429
+ User: "Help me debug this error"
430
+ [Claude uses mask_data tool]
431
+ // → Data masked locally, only [OPENAI_KEY_1] sent to LLM
432
+
433
+ // ✅ GOOD - Using exec_redacted (credential isolation)
434
+ User: "Check why my kubernetes secrets are failing"
435
+ [Claude uses kube_exec tool]
436
+ // → kubectl runs with your credentials
437
+ // → Output masked: "password=[CREDENTIALS_1]"
438
+ // → LLM sees structure but NOT actual credentials
439
+ ```
440
+
441
+ ### Security Model
442
+
443
+ ```
444
+ Your Machine Remote (Anthropic)
445
+ ───────────── ────────────────────
446
+ ┌─────────────────────────────────────────────────────────┐
447
+ │ Sensitive Data: sk-proj-abc123xyz456 │
448
+ │ │
449
+ │ MCP Server masks it → [OPENAI_KEY_1] │
450
+ │ │
451
+ │ Only this is sent → [OPENAI_KEY_1] ──────────────▶ │
452
+ │ │
453
+ └─────────────────────────────────────────────────────────┘
454
+ ```
455
+
456
+ ### Important Limitations
457
+
458
+ 1. **You must actively use the MCP tools** - Claude won't automatically mask everything
459
+ 2. **File reads bypass MCP** - When Claude reads files directly, that data isn't masked
460
+ 3. **MCP mappings are ephemeral** - Stored only in memory, cleared when MCP server restarts
461
+ 4. **Trust model** - You're trusting the llm-mask code running locally
462
+
463
+ ### Best Practices
464
+
465
+ ```bash
466
+ # 1. Scan your codebase before sharing
467
+ llm-mask scan ./src
468
+
469
+ # 2. Use exec_redacted for command output
470
+ llm-mask exec kubectl get secrets
471
+
472
+ # 3. Mask git diffs before sharing
473
+ git diff main | llm-mask diff
474
+
475
+ # 4. When in doubt, pipe through llm-mask
476
+ cat sensitive-file.json | llm-mask | llm # share masked output
477
+ ```
478
+
479
+ ### Summary
480
+
481
+ **Yes, your sensitive data is protected** WHEN you use the MCP tools. But it's not automatic - you (or Claude) need to explicitly use the masking tools. The protection happens **locally before anything leaves your machine**.
482
+
483
+ ## Library Usage
484
+
485
+ ```typescript
486
+ import {
487
+ mask,
488
+ unmask,
489
+ clearMasker,
490
+ Scanner,
491
+ ContextMasker,
492
+ Tokenizer,
493
+ SecureExecutor
494
+ } from 'llm-mask'
495
+
496
+ // Basic masking
497
+ const { masked, mappings, stats } = mask("Email: john@test.com")
498
+
499
+ // Preserve format
500
+ const { masked } = mask("john@test.com", { preserveFormat: true })
501
+
502
+ // Masking levels
503
+ const { masked } = mask(text, { level: 'basic' })
504
+
505
+ // Context-aware
506
+ const contextMasker = new ContextMasker()
507
+ const { masked, context } = contextMasker.mask(jsonString)
508
+
509
+ // Scan codebase
510
+ const scanner = new Scanner({ failOnDetect: true })
511
+ const report = await scanner.scan('./src')
512
+
513
+ // Tokenization
514
+ const tokenizer = new Tokenizer({ salt: 'secure-salt' })
515
+ const token = tokenizer.tokenize('sensitive-value')
516
+
517
+ // Execute commands with credential isolation
518
+ const executor = new SecureExecutor()
519
+ const result = await executor.exec({
520
+ command: 'kubectl',
521
+ args: ['get', 'secrets', '-n', 'production'],
522
+ level: 'standard'
523
+ })
524
+ // result.stdout - original output with credentials
525
+ // result.redacted.stdout - masked output for LLM
526
+
527
+ // Kubernetes convenience
528
+ const kubeResult = await executor.kubectl({
529
+ namespace: 'production',
530
+ pod: 'my-app',
531
+ execCommand: 'env',
532
+ level: 'standard'
533
+ })
534
+
535
+ // SSH convenience
536
+ const sshResult = await executor.ssh({
537
+ host: 'server.example.com',
538
+ user: 'admin',
539
+ remoteCommand: 'cat /etc/secrets/app.conf',
540
+ level: 'standard'
541
+ })
542
+
543
+ // Clear sensitive data from memory
544
+ clearMasker()
545
+ ```
546
+
547
+ ## License
548
+
549
+ MIT
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Audit logging for masking operations
3
+ *
4
+ * Logs masking events WITHOUT the actual sensitive values
5
+ * Only records: timestamp, pattern type, placeholder, length
6
+ */
7
+ export interface AuditEvent {
8
+ timestamp: number;
9
+ patternName: string;
10
+ placeholder: string;
11
+ inputLength: number;
12
+ context?: string;
13
+ }
14
+ export interface AuditLoggerOptions {
15
+ /** Log file path */
16
+ file?: string;
17
+ /** Include in console output */
18
+ console?: boolean;
19
+ /** Context to include in each log entry */
20
+ context?: string;
21
+ }
22
+ /**
23
+ * Audit logger - records masking operations safely
24
+ */
25
+ export declare class AuditLogger {
26
+ private file?;
27
+ private consoleOutput;
28
+ private context?;
29
+ private buffer;
30
+ constructor(options?: AuditLoggerOptions);
31
+ /**
32
+ * Log a masking event
33
+ */
34
+ log(event: AuditEvent): void;
35
+ /**
36
+ * Write event to file (append)
37
+ */
38
+ private writeToFile;
39
+ /**
40
+ * Flush buffer and clear
41
+ */
42
+ flush(): AuditEvent[];
43
+ /**
44
+ * Get buffered events
45
+ */
46
+ getBuffer(): AuditEvent[];
47
+ /**
48
+ * Clear buffer
49
+ */
50
+ clear(): void;
51
+ }
52
+ /**
53
+ * Create audit logger from environment or config
54
+ */
55
+ export declare function createAuditLogger(options?: AuditLoggerOptions): AuditLogger;
56
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,oBAAoB;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAC,CAAQ;IACrB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAC,CAAQ;IACxB,OAAO,CAAC,MAAM,CAAmB;gBAErB,OAAO,GAAE,kBAAuB;IAM5C;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAoB5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAenB;;OAEG;IACH,KAAK,IAAI,UAAU,EAAE;IAMrB;;OAEG;IACH,SAAS,IAAI,UAAU,EAAE;IAIzB;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAM3E"}