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’sproduct.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.
- Patch method
- Enterprise policy
- Use both methods
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 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.jsonas 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_FIREWALLrole. Make sure to install and configure endorctl before you create the key.
<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 example2026-12-31T23:59:59Z.
- macOS:
/Applications/Visual Studio Code.app - Linux:
/usr/share/code, installed from Microsoft’s.debor.rpmpackage - Windows: Program Files, or
%LOCALAPPDATA%\Programs\Microsoft VS Codefor the User Installer
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.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.
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.
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:Remove the daemon
Deployendor-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. WithENDOR_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:
- Generate a Bash VS Code deployment script with your namespace, region, and Package Firewall API key using the generator above.
-
Copy the full URL assigned to
FIREWALL_URLin the Bash script. The URL has this format:For an EU tenant, usefactory.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. -
Deploy
ExtensionGalleryServiceUrlwith that URL in a configuration profile. For platform-specific steps, refer to VS Code enterprise policies. - Restart VS Code and verify that the Extensions view loads through Package Firewall while signed in with an eligible account.
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.- Linux
- Windows
- macOS
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.
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-policyon 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.
- Linux:
/var/lib/endor/vscode-firewall - macOS:
/Library/Application Support/Endor Labs/vscode-firewall - Windows:
%ProgramData%\Endor Labs\vscode-firewall
product.json.
Remove the VS Code configuration
Deployendor-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.jsonwithout reverting other changes in the file. - It removes only the enterprise policy keys that Endor Labs set. It deletes
policy.jsonor 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.
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 inpublisher.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.jsonthat the script does not change. The enterprise policy on the local device does not apply to VS Code Server. - Extensions installed from a downloaded
.vsixfile 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.