For a product with admin controls, offer all three levels and let the more specific rule win. Publisher allowlists are easy but broad. Plugin allowlists are tighter. Version pinning is the strictest and the most work. Most customers will start at publisher level and tighten for sensitive teams.
A real model to compare
VS Code's enterprise documentation shows how an admin control can work. The extensions.allowed setting, available from version 1.96, controls which extensions can be installed. By default all extensions are allowed. Once configured, only listed extensions can be installed and unlisted ones are blocked.
Rules can target three things. A key without a period is a publisher ID. A key with a period is a full extension ID. A value can also list approved versions, optionally with a platform, and there is a "stable" value that blocks pre-release versions. The more specific selector takes precedence, so you can allow a publisher and carve out one extension. Version ranges and wildcards are not supported, except a single star to allow or block everything. If you block an extension or version that is already installed, it is disabled. Organizations can push the setting through an organization policy so users cannot override it.
The three levels compared
| Level | Effort for admin | Protection | Weak spot |
|---|---|---|---|
| Publisher | Low | Broad | Trusts everything the publisher ships later |
| Single plugin | Medium | Good | Still accepts any new version |
| Pinned version | High | Strongest | Updates, including fixes, need manual approval |
Which fits whom
- Small teams without a dedicated security function: publisher level with a short list of well known publishers, plus a blocked list for anything the team has rejected.
- Regulated or high value teams: plugin level, with stable only releases.
- Environments with change control: pinned versions, reviewed on a fixed cadence.
Whatever the level, keep the pin cadence honest. Pinning without an update routine leaves old vulnerabilities in place.
Design points for your own controls
- Default posture. Decide whether new installs start open or closed. VS Code starts open and becomes closed once an admin sets a list. Offering a closed default for enterprise plans may suit your customers better.
- Precedence. State clearly how conflicts resolve. Specific over general is the easiest to explain.
- Existing installs. Define what happens to plugins already in use when a new rule blocks them. Disabling is clearer than silent removal.
- Central enforcement. Provide a policy channel that users cannot override.
- Visibility. Give admins a list of what is installed, by whom, at which version.
- Syntax errors. VS Code notes that a syntax error in the policy value means the setting is not applied. Validate policy files before they ship, and fail loudly.
Allowlists need an inventory
An allowlist controls what can be installed. It does not tell you what is installed now. Without an inventory you cannot know how many copies of a blocked plugin are still active. Pair the control with reporting.
Quick check
Is a blocklist enough instead of an allowlist?
A blocklist handles known bad plugins. An allowlist handles unknown ones. Regulated teams usually want the allowlist, with a blocklist as the emergency tool.
Can admins pin a range of versions?
Not in the VS Code model described here. Each version must be listed, which keeps approvals explicit but means more admin work.
Safeguard's asset discovery and SBOM features support the inventory half of this, and policies and gates handle the rules. You can start with the free scan.
Sources
Last reviewed: 19 October 2026.