Right-click any editor tab to get an unsaved, deterministically anonymized duplicate.
Features
- One Right-Click: Right-click any editor tab title and choose Anonymize & Duplicate Tab. Works on saved files and unsaved (
Untitled-X) buffers alike. - Never Touches Your Source: The sanitized copy opens in a fresh, unsaved buffer that matches the source language mode and syntax highlighting. The original file on disk is never modified.
- Deterministic & Consistent: Identical tokens map to identical surrogates within a session, so
192.167.2.1becomes the same safe IP every time it appears — network paths and identifiers stay readable. - Sequential, Countable Surrogates: IPs, MACs, UUIDs and people are numbered in order of first appearance (
10.0.0.1,10.0.0.2;00:00:00:00:00:00,…:01;user.name1,user.name2), so you can see at a glance how many distinct entities a document contains — and repeats reuse their number. - Secret & Key Redaction: JWTs, Bearer tokens, AWS keys (
AKIA…), GitHub PATs (ghp_…) and credential-bearing database URIs are replaced with<redacted>. PEM / SSH private keys keep theirBEGIN/ENDmarkers — you still see what was removed — with only the key material redacted. - Structured Anonymization: IPv4 / IPv6 / CIDR → RFC 1918 & unique-local ranges, plus UUIDs, MAC addresses, Luhn-valid credit cards and SSNs.
- Smart Emails: Role mailboxes survive (
[email protected]→[email protected]) while people become personas ([email protected]→[email protected]). Domains follow your keyword dictionary rather than being flattened toexample.com. - Custom Keyword Dictionary: Configurable, case-preserving replacements applied inside larger identifiers (
ew1condc01→ew1abcdc01).
Usage
- Open any file or unsaved buffer.
- Right-click the editor tab title.
- Select Anonymize & Duplicate Tab.
A new unsaved editor opens containing the sanitized text. The command is also available from the Command Palette (Cmd+Shift+P / Ctrl+Shift+P) as Anonymize & Duplicate Tab.
Configuration
All settings live under the tabAnonymizer.* namespace:
| Setting | Type | Default | Description |
|---|---|---|---|
tabAnonymizer.customKeywords |
object | {} |
Key → value replacements applied inside identifiers, preserving casing. e.g. { "CON": "ABC", "BEE": "DEF" }. |
tabAnonymizer.redactSecrets |
boolean | true |
Redact tokens, API keys, private keys and credential URIs with <redacted>. |
tabAnonymizer.anonymizeIPs |
boolean | true |
Map IPv4 / IPv6 / CIDR to deterministic private surrogates. |
tabAnonymizer.anonymizeEmails |
boolean | true |
Replace emails: personal local-parts become numbered personas, domains follow the keyword / internal-domain rules. |
tabAnonymizer.preserveRoleEmails |
boolean | true |
Keep role mailboxes (support, info, …) intact instead of replacing them with a persona. |
tabAnonymizer.roleEmailAccounts |
string[] | (common role names) | Local-parts treated as role / shared mailboxes rather than people. |
tabAnonymizer.anonymizeUUIDs |
boolean | true |
Replace UUIDs / GUIDs with deterministic pseudo-UUIDs. |
tabAnonymizer.anonymizeMACs |
boolean | true |
Replace MAC addresses with documentation MACs. |
tabAnonymizer.anonymizeCreditCards |
boolean | true |
Mask Luhn-valid card numbers, keeping the last four digits. |
tabAnonymizer.anonymizeSSNs |
boolean | true |
Mask US SSNs with a test placeholder. |
tabAnonymizer.totalDomainObfuscation |
boolean | false |
Rewrite whole domains rather than relying on keywords — see Domain handling. |
tabAnonymizer.internalDomainSuffixes |
string[] | ["corp.internal", "corp.local"] |
Internal domain suffixes to rewrite. Only used when totalDomainObfuscation is on. |
tabAnonymizer.replacementDomainSuffix |
string | example.internal |
Replacement suffix for matched internal FQDNs. Only used when totalDomainObfuscation is on. |
Example
// .vscode/settings.json
{
"tabAnonymizer.customKeywords": {
"CON": "ABC",
"BEE": "DEF"
}
}
ew1condc01 ➔ ew1abcdc01 · BEE_machine01 ➔ DEF_machine01
Domain handling
By default domains are not rewritten wholesale. Keeping corp.internal intact
while your keyword dictionary handles the identifying part keeps the output easy to
follow — a changed TLD tends to obscure which host was which:
# before
primary: db01.corp.internal
cache: redis01.corp.local
# after (default) — unchanged unless a keyword matches
primary: db01.corp.internal
cache: redis01.corp.local
# after, with "tabAnonymizer.customKeywords": { "corp": "acme" }
primary: db01.acme.internal
cache: redis01.acme.local
Set tabAnonymizer.totalDomainObfuscation to true when you need every domain gone
regardless of the dictionary. It rewrites internalDomainSuffixes to
replacementDomainSuffix and sends unrecognised email domains to example.com:
# after, with totalDomainObfuscation enabled
primary: db01.example.internal
cache: redis01.example.internal
owner: [email protected]
Emails
| Input | Output (with { "contoso": "testltd" }) |
|---|---|
[email protected] |
[email protected] |
[email protected] |
[email protected] |
[email protected] |
[email protected] |
[email protected] |
[email protected] |
Role / shared mailboxes (support, info, noreply, …) are preserved because they
carry no personal data; adjust the list with tabAnonymizer.roleEmailAccounts, or turn
the behaviour off with tabAnonymizer.preserveRoleEmails. A person keeps the same
persona number everywhere they appear, including across different domains.
Requirements
- VS Code
^1.85.0
Contributing
We welcome contributions! Please see our Contributing Guide for details on how to build, test, and submit pull requests.
License
This project is licensed under the MIT License.