@uniglot/wont-let-you-see 0.3.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.
package/README.md CHANGED
@@ -89,46 +89,53 @@ The plugin automatically masks output from:
89
89
 
90
90
  ### AWS Resources
91
91
 
92
- | Pattern Type | Description | Example |
93
- | ------------------ | ---------------------------- | ------------------------------------------------------- |
94
- | `arn` | Generic AWS ARNs | `arn:aws:iam::123456789012:user/admin` |
95
- | `eks-cluster` | EKS Cluster ARNs | `arn:aws:eks:us-west-2:123456789012:cluster/my-cluster` |
96
- | `account-id` | AWS Account IDs (contextual) | `"OwnerId": "123456789012"` |
97
- | `access-key-id` | AWS Access Key IDs | `AKIAIOSFODNN7EXAMPLE` |
98
- | `vpc` | VPC IDs | `vpc-0123456789abcdef0` |
99
- | `subnet` | Subnet IDs | `subnet-0123456789abcdef0` |
100
- | `security-group` | Security Group IDs | `sg-0123456789abcdef0` |
101
- | `internet-gateway` | Internet Gateway IDs | `igw-0123456789abcdef0` |
102
- | `route-table` | Route Table IDs | `rtb-0123456789abcdef0` |
103
- | `nat-gateway` | NAT Gateway IDs | `nat-0123456789abcdef0` |
104
- | `network-acl` | Network ACL IDs | `acl-0123456789abcdef0` |
105
- | `ec2-instance` | EC2 Instance IDs | `i-0123456789abcdef0` |
106
- | `ami` | AMI IDs | `ami-0123456789abcdef0` |
107
- | `ebs` | EBS Volume IDs | `vol-0123456789abcdef0` |
108
- | `snapshot` | EBS Snapshot IDs | `snap-0123456789abcdef0` |
109
- | `eni` | Network Interface IDs | `eni-0123456789abcdef0` |
110
- | `vpc-endpoint` | VPC Endpoint IDs | `vpce-0123456789abcdef0` |
111
- | `transit-gateway` | Transit Gateway IDs | `tgw-0123456789abcdef0` |
112
- | `customer-gateway` | Customer Gateway IDs | `cgw-0123456789abcdef0` |
113
- | `vpn-gateway` | VPN Gateway IDs | `vgw-0123456789abcdef0` |
114
- | `vpn-connection` | VPN Connection IDs | `vpn-0123456789abcdef0` |
115
- | `ecr-repo` | ECR Repository URIs | `123456789012.dkr.ecr.us-west-2.amazonaws.com/my-repo` |
92
+ | Pattern Type | Description | Example |
93
+ | ------------------- | ---------------------------- | ------------------------------------------------------- |
94
+ | `arn` | Generic AWS ARNs | `arn:aws:iam::123456789012:user/admin` |
95
+ | `eks-cluster` | EKS Cluster ARNs | `arn:aws:eks:us-west-2:123456789012:cluster/my-cluster` |
96
+ | `account-id` | AWS Account IDs (contextual) | `"OwnerId": "123456789012"` |
97
+ | `access-key-id` | AWS Access Key IDs | `AKIAIOSFODNN7EXAMPLE` |
98
+ | `secret-access-key` | AWS Secret Access Keys | `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY` |
99
+ | `vpc` | VPC IDs | `vpc-0123456789abcdef0` |
100
+ | `subnet` | Subnet IDs | `subnet-0123456789abcdef0` |
101
+ | `security-group` | Security Group IDs | `sg-0123456789abcdef0` |
102
+ | `internet-gateway` | Internet Gateway IDs | `igw-0123456789abcdef0` |
103
+ | `route-table` | Route Table IDs | `rtb-0123456789abcdef0` |
104
+ | `nat-gateway` | NAT Gateway IDs | `nat-0123456789abcdef0` |
105
+ | `network-acl` | Network ACL IDs | `acl-0123456789abcdef0` |
106
+ | `ec2-instance` | EC2 Instance IDs | `i-0123456789abcdef0` |
107
+ | `ami` | AMI IDs | `ami-0123456789abcdef0` |
108
+ | `ebs` | EBS Volume IDs | `vol-0123456789abcdef0` |
109
+ | `snapshot` | EBS Snapshot IDs | `snap-0123456789abcdef0` |
110
+ | `eni` | Network Interface IDs | `eni-0123456789abcdef0` |
111
+ | `vpc-endpoint` | VPC Endpoint IDs | `vpce-0123456789abcdef0` |
112
+ | `transit-gateway` | Transit Gateway IDs | `tgw-0123456789abcdef0` |
113
+ | `customer-gateway` | Customer Gateway IDs | `cgw-0123456789abcdef0` |
114
+ | `vpn-gateway` | VPN Gateway IDs | `vgw-0123456789abcdef0` |
115
+ | `vpn-connection` | VPN Connection IDs | `vpn-0123456789abcdef0` |
116
+ | `ecr-repo` | ECR Repository URIs | `123456789012.dkr.ecr.us-west-2.amazonaws.com/my-repo` |
116
117
 
117
118
  ### Kubernetes Resources (EKS)
118
119
 
119
- | Pattern Type | Description | Example |
120
- | -------------- | ---------------------------- | ---------------------------------- |
121
- | `k8s-token` | Service Account Tokens (JWT) | `eyJhbGciOiJSUzI1NiIs...` |
122
- | `k8s-endpoint` | EKS Cluster API Endpoints | `https://ABC123.eks.amazonaws.com` |
123
- | `k8s-node` | EKS Node Names | `ip-10-0-1-123.compute.internal` |
120
+ | Pattern Type | Description | Example |
121
+ | -------------- | ------------------------- | ---------------------------------- |
122
+ | `k8s-endpoint` | EKS Cluster API Endpoints | `https://ABC123.eks.amazonaws.com` |
123
+ | `k8s-node` | EKS Node Names | `ip-10-0-1-123.compute.internal` |
124
124
 
125
125
  ### Common Patterns
126
126
 
127
- | Pattern Type | Description | Example |
128
- | ------------- | --------------------------------------------- | ----------------------------------------------------------------- |
129
- | `ipv4` | IPv4 Addresses (including IP portion of CIDR) | `192.168.1.1`, `10.0.0.0/16` → `#(ipv4-1)/16` |
130
- | `private-key` | Private Key Blocks (entire key) | `-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----` |
131
- | `api-key` | API Keys (contextual) | `"api_key": "sk-..."` |
127
+ | Pattern Type | Description | Example |
128
+ | --------------------- | --------------------------------------------- | ----------------------------------------------------------------- |
129
+ | `ipv4` | IPv4 Addresses (including IP portion of CIDR) | `192.168.1.1`, `10.0.0.0/16` → `#(ipv4-1)/16` |
130
+ | `private-key` | Private Key Blocks (entire key) | `-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----` |
131
+ | `api-key` | API Keys (contextual) | `"api_key": "sk-..."` |
132
+ | `phone-us` | US Phone Numbers | `+1-555-123-4567`, `(555) 123-4567` |
133
+ | `phone-kr` | South Korean Phone Numbers | `010-1234-5678`, `+82-10-1234-5678` |
134
+ | `phone-international` | International Phone Numbers | `+44 20 7946 0958` |
135
+ | `email` | Email Addresses | `user@example.com` |
136
+ | `uuid` | UUID/GUID | `550e8400-e29b-41d4-a716-446655440000` |
137
+ | `jwt` | JWT Tokens | `eyJhbGciOiJIUzI1NiIs...` |
138
+ | `base64-secret` | Base64-encoded Secrets (contextual) | `"secret": "SGVsbG8gV29ybGQ="` |
132
139
 
133
140
  ## Token Format
134
141
 
@@ -140,6 +147,10 @@ Examples:
140
147
  - `10.0.0.1` → `#(ipv4-1)`
141
148
  - `10.0.0.0/16` → `#(ipv4-1)/16` (subnet mask preserved)
142
149
  - `AKIAIOSFODNN7EXAMPLE` → `#(access-key-id-1)`
150
+ - `wJalrXUtnFEMI/K7MDENG...` → `#(secret-access-key-1)`
151
+ - `user@example.com` → `#(email-1)`
152
+ - `+1-555-123-4567` → `#(phone-us-1)`
153
+ - `eyJhbGciOiJIUzI1NiIs...` → `#(jwt-1)`
143
154
  - Entire private key block → `#(private-key-1)`
144
155
 
145
156
  ## How It Works
package/dist/index.js CHANGED
@@ -349,6 +349,9 @@ var plugin = async (input) => {
349
349
  return;
350
350
  }
351
351
  output.output = mask(hookInput.sessionID, output.output);
352
+ if (output.metadata?.output) {
353
+ output.metadata.output = mask(hookInput.sessionID, output.metadata.output);
354
+ }
352
355
  },
353
356
  "chat.message": async (hookInput, output) => {
354
357
  for (const part of output.parts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniglot/wont-let-you-see",
3
- "version": "0.3.0",
3
+ "version": "1.0.0",
4
4
  "description": "OpenCode plugin that masks sensitive cloud infrastructure data (AWS, Kubernetes) from LLMs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/patterns/aws.json CHANGED
@@ -6,6 +6,7 @@
6
6
  "contextual": true
7
7
  },
8
8
  "access-key-id": "(?:^|[^A-Z0-9])(?:AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16}(?:[^A-Z0-9]|$)",
9
+ "secret-access-key": "(?:^|[^A-Za-z0-9+/])[A-Za-z0-9+/]{40}(?:[^A-Za-z0-9+/]|$)",
9
10
  "vpc": "^vpc-[0-9a-f]{8,17}$",
10
11
  "subnet": "^subnet-[0-9a-f]{8,17}$",
11
12
  "security-group": "^sg-[0-9a-f]{8,17}$",
@@ -4,5 +4,15 @@
4
4
  "pattern": "\"(?:api_key|apiKey|secret_key|secretKey|access_token|auth_token|password|token)\":\\s*\"([^\"]+)\"",
5
5
  "contextual": true
6
6
  },
7
- "ipv4": "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
7
+ "ipv4": "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
8
+ "phone-us": "^(?:\\+1[-\\s.]?)?(?:\\(?[2-9][0-9]{2}\\)?[-\\s.]?)?[2-9][0-9]{2}[-\\s.]?[0-9]{4}$",
9
+ "phone-kr": "^(?:\\+82[-\\s.]?|0)?(?:1[0-9]|2|3[1-3]|4[1-4]|5[1-5]|6[1-4])[-\\s.]?[0-9]{3,4}[-\\s.]?[0-9]{4}$",
10
+ "phone-international": "^\\+[1-9][0-9]{0,2}[-\\s.]?(?:[0-9][-\\s.]?){6,14}[0-9]$",
11
+ "email": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
12
+ "uuid": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
13
+ "jwt": "^eyJ[A-Za-z0-9_-]*\\.eyJ[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]*$",
14
+ "base64-secret": {
15
+ "pattern": "\"(?:secret|password|credential|private_key|privateKey|encryption_key|encryptionKey|signing_key|signingKey)\":\\s*\"([A-Za-z0-9+/]{32,}={0,2})\"",
16
+ "contextual": true
17
+ }
8
18
  }
@@ -1,5 +1,4 @@
1
1
  {
2
- "k8s-token": "^eyJ[A-Za-z0-9_-]*\\.eyJ[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]*$",
3
2
  "k8s-endpoint": "^https:\\/\\/[A-Z0-9]+\\.[a-z0-9-]+\\.eks\\.amazonaws\\.com$",
4
3
  "k8s-endpoint-kubeconfig": {
5
4
  "pattern": "^https:\\/\\/[0-9A-F]{32}\\.[a-z]{2}-[a-z]+-\\d\\.eks\\.amazonaws\\.com$",
@@ -172,7 +172,8 @@ describe("masker", () => {
172
172
  });
173
173
 
174
174
  it("should not mask ARN when both eks-cluster and arn are revealed", () => {
175
- process.env.WONT_LET_YOU_SEE_REVEALED_PATTERNS = "eks-cluster,arn";
175
+ process.env.WONT_LET_YOU_SEE_REVEALED_PATTERNS =
176
+ "eks-cluster,arn,phone-us";
176
177
  resetConfig();
177
178
 
178
179
  const input =
@@ -210,14 +210,6 @@ describe("Kubernetes Patterns", () => {
210
210
  resetPatternCache();
211
211
  });
212
212
 
213
- describe("Service Account Token", () => {
214
- it("should match JWT format", () => {
215
- const jwt =
216
- "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tYWJjZGUiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjEyMzQ1Njc4LTEyMzQtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.signature";
217
- expect(getPattern("k8s-token").test(jwt)).toBe(true);
218
- });
219
- });
220
-
221
213
  describe("Node Names", () => {
222
214
  it("should match AWS node name", () => {
223
215
  expect(
@@ -334,8 +326,8 @@ describe("loadPatterns", () => {
334
326
 
335
327
  it("should load Kubernetes patterns", () => {
336
328
  const patterns = loadPatterns();
337
- const k8sTokenPattern = patterns.find((p) => p.name === "k8s-token");
338
- expect(k8sTokenPattern).toBeDefined();
329
+ const k8sNodePattern = patterns.find((p) => p.name === "k8s-node");
330
+ expect(k8sNodePattern).toBeDefined();
339
331
  });
340
332
 
341
333
  it("should load common patterns", () => {
package/src/index.ts CHANGED
@@ -30,7 +30,16 @@ export const plugin: Plugin = async (input: PluginInput): Promise<Hooks> => {
30
30
  return;
31
31
  }
32
32
 
33
+ // Mask output sent to LLM
33
34
  output.output = mask(hookInput.sessionID, output.output);
35
+
36
+ // Also mask TUI display (metadata.output is used as fallback in TUI rendering)
37
+ if (output.metadata?.output) {
38
+ output.metadata.output = mask(
39
+ hookInput.sessionID,
40
+ output.metadata.output,
41
+ );
42
+ }
34
43
  },
35
44
 
36
45
  "chat.message": async (hookInput, output) => {