Skip to main content
Package Firewall blocks malicious VS Code extensions before they install. It checks every extension your developers install from the Microsoft Marketplace against your policy, and any extension that does not meet it is never offered for installation. Deploy the VS Code script through an MDM tool such as Microsoft Intune, Jamf, or Kandji. The script routes VS Code through Package Firewall with the patch method, the enterprise policy, or both. Neither method is on by default, so choose at least one when you generate the script. See Choose a method to compare them. View blocked and warned events for VS Code extensions in the Package Firewall logs, filtered by the VS Code ecosystem. See View Package Firewall logs to learn more.

How it works

After you deploy the VS Code script to your developer machines, Package Firewall handles extension installation requests as follows:
1

Point VS Code at Package Firewall

The VS Code script points VS Code’s extension gallery at your Package Firewall URL, through product.json, VS Code’s ExtensionGalleryServiceUrl enterprise policy, or both. After that, VS Code requests extensions from Package Firewall instead of the Microsoft Marketplace.
2

Filter extension requests

Package Firewall checks each requested extension against your policy and returns only the versions that meet it. A version that does not meet the policy is never offered for installation.

Choose a method

The patch method sets the gallery URL in each VS Code installation’s product.json and reapplies it after every VS Code update. The enterprise policy method sets the same URL with VS Code’s ExtensionGalleryServiceUrl enterprise policy, which VS Code updates do not change. The methods are not mutually exclusive, so you can enable either one or both.
The patch method has the following advantages:
  • It covers both the editor and code --install-extension.
  • Users do not need to sign in, so everyone keeps access to the Extensions Marketplace.
  • It is compatible with every VS Code version.
It has the following drawbacks:
  • It depends on a watcher that reapplies the patch after each VS Code update. On macOS, if the daemon cannot patch an update in advance, VS Code can briefly run unpatched and bypass Package Firewall. See Enable VS Code on macOS.
  • On macOS, the daemon re-signs VS Code. Users see keychain prompts after each update, and security rules that match Microsoft’s Team ID no longer match VS Code.
  • On Linux, it requires systemd, and file-integrity tools might report product.json as modified.

Before you begin

Create an API key dedicated to the Package Firewall so that the deployment scripts can authenticate to it. You can create it through one of the following methods:
  • Using the Endor Labs user interface, with the Package Firewall User role. See API keys to learn more.
  • Using endorctl, with the SYSTEM_ROLE_PACKAGE_FIREWALL role. Make sure to install and configure endorctl before you create the key.
To create the key using endorctl, run the following command and replace:
  • <namespace> with your namespace.
  • <API key name> with the name of the API key for the Package Firewall use case.
  • <YYYY-MM-DDTHH:MM:SSZ> with the API key expiration in ISO 8601 UTC format, for example 2026-12-31T23:59:59Z.
The VS Code script manages Microsoft VS Code Stable in its standard location:
  • macOS: /Applications/Visual Studio Code.app
  • Linux: /usr/share/code, installed from Microsoft’s .deb or .rpm package
  • Windows: Program Files, or %LOCALAPPDATA%\Programs\Microsoft VS Code for the User Installer
The script does not manage VS Code Insiders, VSCodium, Code OSS, Snap, Flatpak, Microsoft Store, or portable installations. To deploy the VS Code script on Linux, install Python 3 on the device. The patch method also requires systemd. Whichever method you choose, block marketplace.visualstudio.com/_apis and www.vscode-unpkg.net at your web gateway, so VS Code cannot find or update extensions outside Package Firewall. Do not block *.gallery.vsassets.io or *.gallerycdn.vsassets.io. Package Firewall checks each extension download and then redirects VS Code to those hosts for the file.

Set up the deployment script

Generate the VS Code script, then push it to your developer machines with your MDM tool. Select the methods you want in the generator. For the enterprise policy, you can also choose the account that VS Code asks users to sign in with. See MDM deployment for the upload steps.
If you use Endor Labs with an EU tenant, select the EU region in the generator so the script uses https://factory.eu.endorlabs.com.
For local generation, set ENDOR_VSCODE_ENABLE_PATCH=true, ENDOR_VSCODE_ENABLE_POLICY=true, or both. With the enterprise policy, you can also set ENDOR_VSCODE_POLICY_AUTH to github or microsoft. If you do not set it, VS Code uses its default sign-in account.
Restart VS Code after the first deployment if it is open. The script never removes a method that it was not generated with. See Troubleshoot the VS Code script if a method from an earlier deployment is still in place. Scripts generated before these options patched VS Code on Linux and Windows by default. Those scripts keep working until you replace them. To keep patching after you regenerate, select the patch method. In the Bash script, the patch method also turns on the re-signing daemon on macOS. To patch only Linux, deploy endor-vscode.sh to Linux machines only. ENDOR_VSCODE_MACOS_DAEMON from earlier generator versions still works as another name for ENDOR_VSCODE_ENABLE_PATCH. As a result, ENDOR_VSCODE_MACOS_DAEMON=0 now turns the patch method off on Linux too. If one variable turns the patch method on and the other turns it off, generate.sh stops with an error.

Enable VS Code on macOS

On macOS, the patch method installs a root launch daemon for Microsoft VS Code Stable at /Applications/Visual Studio Code.app. The daemon checks a copy of VS Code in a directory that only root can access. It patches and signs that copy with a certificate unique to the Mac, then swaps it into /Applications. This avoids breaking the installed app’s signature by editing it in place. The signing key stays in the System keychain, and you cannot export it. When VS Code downloads an update, the daemon prepares a patched, signed copy before the updater installs it. If preparation fails, VS Code can install Microsoft’s build, and the daemon handles it afterward. Keep this possible gap in mind when planning enforcement.
Re-signing changes VS Code’s identity. Users receive a keychain password prompt at the first migration and after each update, and privacy permission prompts again at migration. Endpoint security and allowlisting rules that match Microsoft’s signer or Team ID no longer match the re-signed app. Review those rules before deploying.
At the keychain prompt for Code Safe Storage, select Always Allow to let VS Code access saved sign-ins. Denying access hides those sign-ins for that session without deleting them. The re-signed app is no longer notarized by Microsoft. The daemon refuses apps with an unexpected signer or changes beyond its own managed patch. To leave VS Code’s signature unchanged on macOS, use the enterprise policy instead and deliver it with a configuration profile. See Deliver the enterprise policy on macOS.

Check the daemon

Run these commands as root to inspect the daemon’s status and recent log entries:
For more information, refer to the macOS code-signing details.

Remove the daemon

Deploy endor-vscode-disable-patch.sh or endor-remove.sh to restore Microsoft’s original app and remove the signing identity. If no original is available, the script restores the default gallery settings in a copy. A copy signed by the daemon stays re-signed until VS Code’s next update replaces it with Microsoft’s build.

Deliver the enterprise policy on macOS

On Linux and Windows, the VS Code script sets the enterprise policy. On macOS, VS Code reads the policy only from an MDM configuration profile, so the script checks for the profile instead of writing the policy. With ENDOR_VSCODE_ENABLE_POLICY=true, generate.sh writes the profile to out/<namespace>/ as endor-vscode.mobileconfig, and as endor-vscode-policy.plist for MDM tools that ask for a preference file. Upload one of them to your MDM tool. Both contain the credential. For steps in Jamf Pro, Kandji, Intune, and JumpCloud, refer to The macOS profile. Only generate.sh creates these files. The browser generator and generate.ps1 do not. To build the profile from a script generated in the browser:
  1. Generate a Bash VS Code deployment script with your namespace, region, and Package Firewall API key using the generator above.
  2. Copy the full URL assigned to FIREWALL_URL in the Bash script. The URL has this format:
    For an EU tenant, use factory.eu.endorlabs.com. The token encodes <api-key-id>:<api-secret> as base64url without padding. Treat the full URL as a credential and replace it when rotating the API key.
  3. Deploy ExtensionGalleryServiceUrl with that URL in a configuration profile. For platform-specific steps, refer to VS Code enterprise policies.
  4. Restart VS Code and verify that the Extensions view loads through Package Firewall while signed in with an eligible account.
Upload one profile for the com.microsoft.VSCode preference domain. If another profile already manages it, such as one based on Microsoft’s sample, add the Endor Labs keys to that profile instead. With two profiles, macOS does not define which one applies. When you rotate the API key, regenerate the files and replace the profile in your MDM tool. VS Code asks users to restart when the policy changes. To check the policy on a Mac, run the following command. In VS Code, the Developer: Policy Diagnostics command also lists the policies that VS Code applies.

Troubleshoot the VS Code script

The VS Code script fails on devices where a method from an earlier deployment is still in place, but the script was not generated with that method. The script does not remove the method. It prints a warning and exits with code 1, so your MDM tool reports a failure. Regenerate the script with that method to keep it, or turn the method off with its disable script. See Switch or turn off a VS Code method. The script also prints a warning and exits with code 1 if VS Code is older than the minimum version for the enterprise policy. See Choose a method. With the patch method enabled, it prints a note instead, because the patch covers older versions. If you choose a sign-in account and VS Code is older than the minimum version for it, the script exits with code 1 even with the patch method enabled. Other reasons the script can fail depend on the platform.
The script fails if Endor Labs did not configure the gallery URL or sign-in account in the enterprise policy.Fix /etc/vscode/policy.json and deploy the script again if the file does not meet these requirements:
  • It is a regular file, not a symbolic link.
  • It is owned by root.
  • Other users cannot write to it.
  • It contains a valid JSON object.
File-integrity tools such as debsums, rpm -V, and AIDE might report product.json as modified after the patch method runs. This is expected because the patch modifies this file.

Switch or turn off a VS Code method

The generators also write one disable script per method, endor-vscode-disable-patch and endor-vscode-disable-policy. Each script turns off its method and leaves the other method and the package manager configuration in place. To generate one in the browser, select it as the ecosystem in the MDM script generator. To turn off both methods, deploy both disable scripts. You can also deploy the remove script, which also removes the package manager configuration. The disable scripts run as root or SYSTEM and do not need a user signed in to the device. They accept --dry-run, or -DryRun on Windows. To keep Package Firewall on while you switch methods, deploy the new method before you turn off the old one:
  • Patch to enterprise policy: Deploy a VS Code script generated with only the enterprise policy, and upload the profile for macOS. Then deploy endor-vscode-disable-patch.
  • Enterprise policy to patch: Deploy a VS Code script generated with only the patch method. Then deploy endor-vscode-disable-policy on Linux and Windows, or remove the profile in your MDM tool on macOS.
  • Both to one: Deploy a VS Code script generated with the method you keep. Then deploy the disable script for the other method.
The new VS Code script prints a warning and exits with code 1 until the old method is gone, so your MDM tool reports a failure until then. The script still applies the new method on that run. Unassign any older VS Code script in your MDM tool, because a script generated with a method turns it on again at its next run. The patch method can be turned off only while its worker, the program that applies the patch, is still in its state folder:
  • Linux: /var/lib/endor/vscode-firewall
  • macOS: /Library/Application Support/Endor Labs/vscode-firewall
  • Windows: %ProgramData%\Endor Labs\vscode-firewall
If someone deleted that folder, reinstall VS Code to restore Microsoft’s product.json.

Remove the VS Code configuration

Deploy endor-remove.sh or endor-remove.ps1 to remove the methods that the VS Code script set:
  • It stops the watcher and restores the default gallery values in product.json without reverting other changes in the file.
  • It removes only the enterprise policy keys that Endor Labs set. It deletes policy.json or the registry key only if the VS Code script created it and nothing else remains in it. The disable scripts follow the same rule.
  • On macOS, it restores Microsoft’s original app when one is available. See Remove the daemon.
On macOS, the remove script does not remove an enterprise policy that you delivered with a configuration profile. It prints a warning and exits with code 1 while a profile still sets an Endor Labs URL. Remove the profile in your MDM tool.

Package Firewall policy

A Package Firewall policy for VS Code extensions supports the malware and minimum package age conditions. Package Firewall removes extension versions that meet a condition from Microsoft Marketplace results. If no version remains, or a developer downloads a version directly, Package Firewall blocks the request. To always allow a specific extension, add an exception using the extension’s identifier in publisher.name form, such as ms-python.python. This identifier appears as the unique identifier on the extension’s Marketplace page, and in the extension’s details in VS Code. You can allow all versions of the extension, a specific version, or a range of versions. See Package Firewall policy to learn more.

Response codes

Package Firewall returns the following HTTP status codes to VS Code for extension requests.

Limitations

Keep the following limitations in mind when using Package Firewall for VS Code extensions:
  • Package Firewall covers only the extensions available in the Microsoft Marketplace, the default for official Microsoft builds of VS Code. It does not cover the Open VSX registry, which is the default for VSCodium and Cursor.
  • The VS Code script does not cover extensions installed on a remote machine that VS Code connects to over SSH, to WSL, or through a tunnel. These connections run VS Code Server, which uses its own product.json that the script does not change. The enterprise policy on the local device does not apply to VS Code Server.
  • Extensions installed from a downloaded .vsix file do not go through the Marketplace, so Package Firewall cannot filter them. Disable file-based installation with a VS Code enterprise policy to close this gap.
  • For an extension that publishes thousands of versions, Package Firewall may not check the oldest ones. If Package Firewall blocks every version it checks, you cannot install the extension.