Safeguard
Software Supply Chain•

How do you build a VS Code extension, and what should you secure?

Scaffold with Yeoman, run it in the Extension Development Host, add a command in package.json, then lock down dependencies, permissions and publishing.

Safeguard Security Team
4 min read

To build a VS Code extension, scaffold a project with the Yeoman generator, press F5 to launch an Extension Development Host window, register a command in extension.ts and declare it in package.json. Because extensions run with your user's rights, treat dependencies and publishing as security work.

How do you create the first extension?

The official guide starts with Node.js and Git installed, then runs the Yeoman generator through npx. You choose a new extension in TypeScript, name it, accept defaults for the identifier, leave the description blank, initialize a git repository, pick unbundled and choose npm as the package manager. Then open the folder in VS Code.

Open src/extension.ts and press F5, or run Debug: Start Debugging from the Command Palette. This compiles the extension and runs it in a new Extension Development Host window. In that window, run the Hello World command from the Command Palette and you should see a notification.

If the command does not appear, the docs say to check package.json and make sure the engines.vscode version is compatible with your installed VS Code.

How does a command get wired up?

Two places have to agree. In package.json, contribution points are static declarations that extend the editor, such as commands, menus and keybindings. In extension.ts, code registers the handler for the same command identifier.

To change behavior, edit the message in extension.ts, then run Developer: Reload Window in the development host window and run the command again. The docs suggest next steps such as renaming the command, adding a second command that shows the time, or replacing the information message with a warning.

How do you debug?

VS Code's built-in debugging works on extensions. Set a breakpoint in the gutter and it will hit when the command runs. You can hover over variables, use the Run and Debug view and evaluate expressions in the Debug Console. The docs point to the Node.js debugging topic for more.

What should you secure?

An extension is a Node.js program that runs inside a developer's editor, with access to their files and often their credentials. That makes it a supply chain target, in both directions: your extension depends on npm packages, and your users depend on your extension.

Keep dependencies few. Every package you add runs on your users' machines. Commit your lock file and install with npm ci in your build, since that command installs from the lock file, never writes to package.json or the lock, and errors on mismatch. Run npm audit in your pipeline, and use npm audit signatures to verify registry signatures and provenance attestations of downloaded packages.

Request only what you need. If the extension reads files, limit it to the workspace folder. Do not send source code or file names to a server unless the user has agreed and you say so plainly.

A constructed example

A team builds an extension that adds a command to insert a company license header. It needs no network, one dependency for template handling and read access to the open file. They commit the lock file, pin the build to npm ci and publish from a protected branch with two person review. A reviewer asking "why does this extension need a network library?" is the kind of question that catches trouble early.

How to check or apply this

  1. Scaffold with the Yeoman generator and run it with F5 before you change anything.
  2. Declare commands in package.json and register them in extension.ts.
  3. Debug with breakpoints in the Extension Development Host.
  4. Keep the dependency list short and review each addition.
  5. Commit the lock file and build with npm ci.
  6. Run npm audit and npm audit signatures in the pipeline.
  7. Limit file and network access to what the feature needs, and document it.
  8. Protect the publishing credentials and require review before release.

Quick check

What is the Extension Development Host?

A separate VS Code window that loads your in-development extension so you can run and debug it without installing it.

Why use npm ci instead of npm install in a build?

It installs exactly what the lock file says and fails if package.json and the lock disagree, which makes builds repeatable.

Sources

  1. Visual Studio Code, Your First Extension
  2. npm Docs, npm ci
  3. npm Docs, npm audit

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.