Hardening#
The editor is one of the most-privileged programs on the operator’s workstation. It reads source code, holds API tokens, runs language servers, executes tasks, and (through plugins) ships fresh code from strangers on the internet straight into the same process as the operator’s work. Compromise the editor and the supply chain, the credentials, and the lateral path are all already loaded.
This page is the defender’s checklist for that surface: threat model, extension hygiene, sandboxing, credential separation, and the practical settings that shrink what a malicious extension or poisoned update can reach.
Threat Model#
What an attacker actually wants from your editor. The list below is sorted roughly by impact; source code and credentials are the direct prizes; lateral movement and supply-chain entry are the larger ones once an editor is compromised:
Source code, proprietary product, customer data, secrets in config files.
Credentials, AWS / GCP / Azure tokens, GitHub tokens, SSH keys, cloud-provider sessions,
.envfiles.Sessions, browser cookies stored in the same OS profile, mail client tokens, password manager state.
Lateral movement, the developer’s machine has access to internal services that production hosts don’t.
Supply-chain entry, a compromised editor that injects malicious code into commits poisons what gets pushed to production.
Because the editor sits between every other tool, it’s a high-value single point of compromise.
The Extension Marketplace Problem#
VS Code, Cursor, JetBrains, Zed, and Sublime all have public marketplaces where anyone can publish. The marketplaces include some review, but the volume makes deep review impossible; and an extension is not data, it is a full program with the same access the editor has.
Real-world attack patterns:
Typosquatting,
dracula-themeeinstead ofdracula-theme.Maintainer takeover, abandoned popular extensions are sold or taken over; new owners push malicious updates.
Update poisoning, a legitimate extension publishes a malicious version. Auto-update pulls it in.
Bundled trojans, “themes” or “snippet packs” that include arbitrary executable code (extensions in most editors are full programs, not data).
Dependency confusion, the extension itself is fine but pulls npm / PyPI dependencies an attacker has hijacked.
Mitigations:
Pin extension versions, in VS Code,
"extensions.autoUpdate": false; review changelogs before manual updates.Audit installed list periodically; uninstall anything you don’t actively use.
Prefer first-party extensions from the language-server vendor.
Check publisher, a “verified publisher” check exists in most marketplaces; it’s weak but better than nothing.
Sandboxed dev environment, run the editor where it doesn’t have access to your real tokens (see below).
Workspace Trust#
A first line of defense built into modern editors. The first time you open a project the editor asks whether to “trust” it; until you say yes, extensions, tasks, and debug configs are restricted.
VS Code / Cursor, “Workspace Trust” panel; restricted mode shows a banner. Configure in
security.workspace.trust.untrustedFilesand similar settings.JetBrains, “Trusted Locations” dialog; set
Settings → Build → Trusted Locations.Zed, per-project allow-list before running tasks or extension commands.
Workspace trust is meaningful because opening a repo can run code.
A malicious .vscode/settings.json can point python.defaultInterpreterPath
at a script in the repo; opening the project then runs that script.
Default to untrusted. Only trust repos you control or have read.
Settings That Leak#
A handful of editor settings have direct security implications, telemetry, settings sync, AI features, crash reporters. Each one can leak source, filenames, or credentials by default; auditing these toggles per editor is the cheapest hardening you can do:
Telemetry, VS Code has
telemetry.telemetryLevel; set tooffor use VSCodium. JetBrains has telemetry underSettings → Appearance & Behavior → System Settings → Data Sharing.Crash reports, often include partial source; review what they upload.
Settings sync, VS Code / Cursor sync settings via Microsoft / GitHub accounts. Pin which settings sync; don’t sync MCP servers, AI provider keys, or anything secret-shaped.
Auto-fetch / auto-save in shared repos, can leak filenames you haven’t committed yet to remote services.
AI features, some send file contents to model providers by default. Read the privacy policy; flip “privacy mode” or “private projects” where it exists.
AI / Copilot Considerations#
AI coding assistants are valuable and risky; the same model that suggests fixes also reads your code, and what it does with that code afterwards depends on a setting most users never check. Operators on sensitive repos should treat AI features as a deliberate decision per project, not an editor default.
Code goes off-machine in default modes. Confirm whether the provider stores or trains on your code.
“Privacy mode”, Cursor, GitHub Copilot, Codeium, JetBrains AI all offer modes that disable training and reduce retention. Verify the mode is on for sensitive repos.
Self-hosted models, Ollama, vLLM, llama.cpp let you keep context local. Pair with editors that support custom endpoints (Continue, Zed, Cursor’s BYOK mode).
Local-only patterns,
.aiignore/.gptignorefiles are becoming common; secrets directories, generated code, and large binary blobs typically go in them.Audit prompts, some agentic features will run shell commands. Read the proposed action before approving.
Secrets and Tokens#
The most common lossage. The pattern is almost always the same: a token ends up in a file the editor opens, then leaks via settings sync, an AI provider, or a plugin with too much access. Discipline below; the goal is to keep tokens out of any file the editor touches in the first place:
Discipline:
Never keep tokens in source, not in
.envchecked in, not in JSON config, not in JetBrains run configurations that get committed.Use OS keychains (macOS Keychain, Windows Credential Manager,
secret-toolon Linux + GNOME Keyring / KWallet) or password managers (1Password CLI, Bitwarden CLI,pass).For local
.envfiles,.env.examplein source + real.envin.gitignore+direnvto load.Pre-commit secret scanning,
gitleaks,trufflehog, ordetect-secretsin a pre-commit hook.Rotate anything that touches a public LLM, even briefly.
Audit ``.gitignore`` so editor backup files (
*.swp,*~,.idea/workspace.xml) and AI / chat history don’t sneak in.
Sandboxed Development#
Run the editor where compromise hurts less. The goal is to limit what a malicious extension can reach. If the editor never sees your real cloud credentials or SSH keys, even a fully-compromised plugin has very little to steal:
Dev Containers (VS Code, JetBrains, Zed, GitHub Codespaces), the editor is on your machine, the project + extensions + language servers run in a container. Tokens scoped per-container.
VMs, a per-engagement VM (Linux distros, macOS Parallels) for particularly sensitive work; tear down at the end.
Per-project user accounts, separate OS users for “work”, “personal”, “untrusted experiments”. Crude but effective.
WSL / Multipass / Lima, Linux-VM-per-project on Windows / macOS.
The blast radius of a malicious extension drops dramatically when it runs in an environment that doesn’t have your real keys.
Code Signing / Commit Signing#
Even if your editor is compromised, signed commits make tampering detectable downstream. The bar is not perfect prevention. A compromised editor can still produce a signed commit if the key is unlocked, but signing plus hardware keys plus branch protection makes silent supply-chain attacks much harder:
GPG / SSH commit signing,
git config commit.gpgsign truewith an SSH or GPG key.Hardware-backed keys, YubiKey or Apple Passkey-derived SSH keys prevent silent key theft.
GitHub / GitLab “verified” badge, visible signal in the UI.
Branch protection, require signed commits; reject pushes that don’t have valid signatures.
A compromised editor can still produce signed commits if the key is unlocked; hardware keys with a touch-to-sign requirement raise the bar.
SSH and Cloud Access#
The editor often holds the keys to cloud accounts and remote servers, either directly (SSH keys, AWS profiles) or via the shell environment it inherits. Hardware-backed keys and short-lived credentials limit how much an attacker gets when the editor is compromised:
SSH agent socket, only forward when needed (
ssh -Ais convenient and dangerous on shared servers).Hardware-backed SSH keys,
ssh-keygen -t ed25519-sk(FIDO2 security key); cannot be exfiltrated.Short-lived credentials, use IAM role assumption (AWS) / workload identity (GCP) / managed identity (Azure) instead of long-lived static keys checked into editor config.
OIDC for CI, avoids storing static cloud keys in editor secrets at all.
Editor-Specific Notes#
The hardening levers worth knowing per editor. Each one has its own auto-update default, plugin format, and “open this file and something runs” pattern; the items below cover the highest-impact toggles for the editors most operators use.
VS Code / Cursor
security.workspace.trust.enabled:true(default).extensions.autoUpdate:falseif you want to review.security.allowedExtensions: explicit allowlist on managed setups.For extension review, see
code --list-extensions --show-versions.On Linux, Snap / Flatpak builds run sandboxed by default.
JetBrains
“Trusted Locations”, restrict to specific directories.
Settings → Plugins → Marketplace, many companies use a custom plugin repository / proxy.Updates and Plugins, consider disabling auto-update for consistency; review updates manually.
Vim / Neovim
set nomodeline, modelines (# vim: ft=python ts=2) can run arbitrary commands on file open. Disable.Plugins are full Vimscript / Lua. Pin versions in lazy.nvim / packer.nvim.
Treat
.vimrc/.exrcfiles inside repos as untrusted (Vim’sset nosecuremakes this configurable).
Emacs
enable-local-variables,:safeorqueryotherwise file- variables can run arbitrary elisp.enable-dir-local-variables: similar for.dir-locals.el.MELPA / NonGNU ELPA / GNU ELPA, prefer signed packages where available.
Sublime Text
Package Control packages are Python; review what you install.
“Disabled packages” setting to keep risky ones out of the load order.
Helix / Zed
Smaller plugin attack surface today; this changes as their plugin systems mature. Track that.
Operational Practices#
The day-to-day discipline that keeps editor-derived risk contained, encrypted backups, encrypted disk, screen lock, short keychain timeouts, periodic credential rotation. None of them is new; all of them help when something does leak:
Backup encryption, whatever Time Machine / Restic / Arq produces shouldn’t include unencrypted tokens.
Disk encryption, FileVault / BitLocker / LUKS by default.
Auto-lock screen, when you walk away.
Keychain unlock policy, short timeout for sensitive keychains.
Periodic credential rotation, assume something has leaked you haven’t noticed.
When in Doubt#
A short list of “stop and think” prompts. Each one corresponds to a real attack pattern (recommended-extension trojans, kiosk machines, post-CVE exposure) and the right answer is usually “sandbox first, then decide”:
Untrusted code, open in a sandboxed environment first (Dev Container, VM, or even
code --disable-extensions).Strange repo offers a recommended extension, decline. Recommended extensions are a Trojan-horse delivery vector.
Editor is on a shared / kiosk machine, log out the personal account; use a guest profile.
Vendor announces a security advisory, update the editor first; audit installed extensions; rotate any tokens that may have been exposed.
See also: hardening for system-level
hardening; Security for the broader software
supply-chain story.