Sether for VS Code
Detect and replace supported patterns of personal data and secrets in your editor before you choose to share text. Local processing. No telemetry. No account.
Sether runs the same deterministic detection engine as @raeven-co/sether (npm), sether (PyPI) and the Sether Shield browser extension, inside your editor:
- Squiggles in the Problems panel for emails, phones, card numbers, SSNs, IBANs, public IPs, vendor API keys (OpenAI, Anthropic, AWS, GitHub, Slack, Stripe), JWTs, database URIs with passwords,
DB_PASSWORD=... assignments and PEM private keys. Secrets are errors, personal data is a warning. Both are configurable.
- Quick fixes on every finding: mask (
e***@a***.com), redact ([email-1]) or swap for a decoy (jane.doe@example.com, a 555-01XX phone, a Luhn-valid card). Decoys use fictional examples and reserved ranges where available; review replacements before sharing.
- Copy Scrubbed before you paste into Copilot Chat, Cursor, Claude or ChatGPT, and Paste with Originals Restored when the answer comes back. The mapping lives in memory for the session and nowhere else.
- Scan Workspace to inspect supported files in the current working tree. Optional Fix all on save replaces detected findings when the configured save action runs.
- Hover on a finding to see why it matters and which control it maps to (GDPR Art. 28, PCI DSS Req. 3.4, SOC 2 CC6.1, ...).
- Watchlist: point
sether.watchlistFile at a CSV of your own names, emails and codenames, each with its own action. Same file format as Sether Shield.
Restore Originals restores recognized replacements while the session mapping remains available. Detection and restoration are best-effort; review the result.
Install
- VS Code: search for Sether in the Extensions view, or
ext install GodfreyLebo.sether.
- Other compatible editors: use their Install from VSIX command with the release package. Marketplace availability varies by editor.
- Any editor: download the
.vsix from the releases page and run code --install-extension sether-<version>.vsix.
No configuration needed. Open a file with an email in it and the status bar shield turns orange.
What it catches
| Pack |
Types |
Default |
Method |
| Basic |
Email, phone (multi-region), card number, SSN, IBAN |
on |
Validated patterns: Luhn, mod-97, SSA prefix rules, libphonenumber |
| Network |
IPv4, IPv6 |
on |
Strict octet and hextet grammar. Separate toggle for infra-heavy repos. |
| Secrets |
OpenAI, Anthropic, AWS, GitHub, Slack and Stripe keys, JWTs, label-anchored api_key = ... and password: ... |
on |
Published vendor prefixes and lengths |
| Credentials |
postgres://user:pass@host, SECRET_KEY=..., -----BEGIN PRIVATE KEY----- |
on |
Scheme, name and PEM shape |
| Identity |
Label-anchored names, dates of birth, passport numbers, addresses (customer_name: ..., "dob": "...") |
off |
Multilingual labels, JSON keys |
| High entropy |
Long random strings with no known prefix |
off |
Shannon entropy over 32+ char tokens |
The engine uses the published @raeven-co/sether package. Results depend on the package version, enabled packs and configuration; review findings and omissions.
What it deliberately skips
Values that cannot belong to a real person or system are not flagged (sether.ignoreReservedValues):
example.com, .test, .invalid, localhost email domains
- loopback, private, link-local and documentation IP ranges (
127.0.0.1, 10.0.0.0/8, 192.168.0.0/16, 192.0.2.0/24, ::1, 2001:db8::/32)
- fictional phone ranges: NANP
555-01XX, Ofcom drama numbers
- documented test cards (
4242 4242 4242 4242) and example IBANs
- the SSA advertising SSN block,
John Doe
- numbers glued into SVG path data and coordinate blobs, millisecond timestamps that happen to pass Luhn, tracking IDs like
AW-1719..., and code expressions such as password: values.password or password: Yup.string()
Sether's own decoys come from these ranges, so a decoy you swapped in scans clean.
Commands
All commands are under the Sether category in the Command Palette, in the editor context menu under Sether, and behind the status bar shield.
| Command |
What it does |
| Scan Current File |
Re-scan the active editor now. |
| Scan Workspace |
Scan every text file in the workspace (respects files.exclude, search.exclude and sether.exclude). Results land in the Problems panel. |
| Scrub Selection or File... |
Pick mask / redact / decoy and replace every finding in the selection (or the whole file). |
| Scrub All Findings in File |
Same, with your default action, no prompt. |
| Copy Scrubbed (for AI chat) |
Copy the selection (or file) with findings replaced. Ctrl/Cmd+Alt+Shift+C. |
| Paste with Originals Restored |
Paste the clipboard with every known replacement swapped back. Ctrl/Cmd+Alt+Shift+V. |
| Restore Originals in Selection or File |
Reverse earlier scrubs in place. |
| Forget Session Vault |
Drop all replacement mappings. Earlier scrubs can no longer be restored. |
| Reload Watchlist |
Re-read the watchlist file. |
| Enable / Disable |
Toggle scanning. |
The AI round trip
- Select the code or log you want help with. Run Copy Scrubbed.
- Paste into your AI assistant. It sees
[email-1], a***@a***.io or jane.doe@example.com depending on your default action. Decoys can keep examples readable; check whether substitutions affect the answer.
- Copy the reply. Run Paste with Originals Restored in your editor. Recognized replacements are restored when the corresponding session mappings are available.
The vault mapping decoys to real values is memory-only: never written to globalState, workspaceState, disk or logs. It dies with the extension host.
Fix all on save
// settings.json
"editor.codeActionsOnSave": {
"source.fixAll.sether": "explicit"
}
Every finding in a saved file is replaced with your sether.defaultScrubAction. Use "always" to run on auto-save too.
Suppressing a finding
Inline, like any linter. The value never gets copied into a settings file:
const supportEmail = 'ops@acme.io'; // sether-ignore-line
// sether-ignore-next-line
const bootstrapKey = process.env.KEY ?? 'AKIA...';
// sether-ignore-file
The Ignore this line quick fix inserts the comment for you in any language with line comments. For shared test data that is genuinely not sensitive, sether.ignoreValues takes exact strings.
Watchlist
A CSV of values only you know are sensitive: your name, internal codenames, customer emails. One line per value, with its own action and optional fixed replacement:
term,action,replacement,match_case,whole_word
Godfrey Lebo,decoy,John Doe,no,yes
Raeven Company,redact,[my-company],no,yes
Project Falcon,mask,,no,yes
Set sether.watchlistFile to the path (relative to the workspace root, or absolute). The file is re-read when it changes. Terms are matched literally, whole-word and case-insensitively by default. The same file works in Sether Shield.
Settings
| Setting |
Default |
Notes |
sether.enable |
true |
Master switch. |
sether.scanTrigger |
onType |
onType, onSave or manual. |
sether.debounceMs |
400 |
Delay after the last keystroke. |
sether.maxFileSizeKb |
512 |
Larger files are skipped. |
sether.exclude |
node_modules, .git, dist, lockfiles, binaries, ... |
Globs matched against the absolute path. |
sether.packs.basic / network / secrets / credentials |
true |
See the table above. |
sether.packs.identity |
false |
Label-anchored names, DOB, passport, address. |
sether.packs.highEntropy |
false |
Unknown-prefix secrets. Can flag hashes and commit SHAs. |
sether.phoneRegions |
US, GB, NG, CA |
Regions for numbers written without a country code. |
sether.ignoreReservedValues |
true |
Skip reserved, fictional and private values. |
sether.ignoreValues |
[] |
Exact values to never flag. |
sether.watchlistFile |
"" |
Path to the watchlist CSV. |
sether.severity.secrets / pii / watchlist |
error / warning / warning |
Problem severity per category. |
sether.defaultScrubAction |
mask |
mask, redact or decoy. |
sether.statusBar |
true |
Show the status bar item. |
Privacy
- No network calls. The shipped bundle is checked on every build for
fetch, XMLHttpRequest, WebSocket, http, net, dns, tls and child_process. The build fails if any appear.
- No telemetry, no accounts, no servers. Nothing is counted, nothing is sent.
- No value is ever logged. Diagnostics, hovers and the output log show masked previews only (
a***@a***.io).
- The session vault is not persisted. Watchlists remain in the files you create. Scrub and restore commands can edit your documents or clipboard; ordinary editor save behavior still applies.
- Untrusted workspaces are supported. Sether reads text, it never runs workspace code.
The source is small. Read src/ and the CI guard in scripts/check-no-network.mjs.
Limitations
Sether does not intercept network traffic or prevent other software from transmitting a document. It cannot guarantee detection of every sensitive value.
Free-text names in running prose (no label, no watchlist entry) are not detected. That needs the NER model in @raeven-co/sether-ner, which is on the roadmap for the editor.
Detection is per document. A secret split across two files is two problems, not one.
The workspace scan does not read .gitignore. Use sether.exclude or files.exclude. Template files (.env.example, *.sample) are excluded by default because their values are placeholders by convention.
Restore works while the extension host is alive. Reload the window and the vault is gone. That is deliberate.
License
MIT. A product of Raeven Company LTD.
| |