Safeguard
Developer Tools•

vcpkg manifest mode or classic mode: which is safer to ship from?

Manifest mode records dependencies in vcpkg.json and enables version pinning. Classic mode installs one global set. Why it matters for patching.

Safeguard Security Team
3 min read

For anything you ship, use manifest mode. It declares dependencies in a vcpkg.json file in your repository and is required for version constraints, baselines and overrides. Classic mode installs packages into one shared tree with one version of each port, which makes builds depend on whatever is installed on the machine.

The difference in one table

QuestionManifest modeClassic mode
Where are dependencies declared?vcpkg.json in the projectInstall commands, in your head or a script
Version pinningBaselines, constraints and overridesNot available
Install locationvcpkg_installed next to the manifestOne global installed folder
Versions per librarySeparate per projectOne per port

Microsoft's documentation recommends manifest mode for most users and states that versioning and custom registries require it. It also says per-manifest install trees separate dependencies between projects and avoid classic mode's limit of one version of each port.

Why this matters for security

Three practical effects:

  1. Reviewability. A change to vcpkg.json is a commit. You can see who raised or lowered a version and when.
  2. Reproducibility. Two developers and CI use the same baseline, so they link the same library versions.
  3. Isolation. A security fix for project A does not accidentally change project B, and project B cannot be blocked from a fix by project A.

Classic mode has none of these. Two machines can have different libraries with no record in the repository, and the global tree changes whenever someone installs something.

There is one more catch. A manifest without a baseline behaves as classic mode with respect to versions. The versioning reference says that without a builtin-baseline, and with no registries configured, the install follows the classic algorithm and ignores versioning information. So being in manifest mode is not enough: add the baseline.

A concrete scenario

Suppose a compression library gets a fix. In manifest mode, you raise the constraint in vcpkg.json, open a pull request, and CI builds against the new version in a clean vcpkg_installed folder. Reviewers see the change, and the merge is your evidence. In classic mode, somebody runs an upgrade on a build machine, nobody records which machine, and a developer laptop keeps the old copy until it is refreshed. The fix exists, but you cannot show where it landed.

Moving a project over

  1. Create vcpkg.json with the names you currently install.
  2. Add an initial baseline using the add-initial-baseline option of the update-baseline command.
  3. Build clean and compare library versions with your old install.
  4. Remove the global install from CI images so nothing falls back to it.
  5. Commit and document how to update the baseline.

Try it yourself

Open the demo and compare an inventory to what you would see from a manifest. A declared file is the easiest starting point for a complete list.

Click through it at your own pace, or open it full screen.

Quick check

Is classic mode wrong for experiments?

It is fine for quick trials. Do not ship a product from it.

Does manifest mode pin versions automatically?

Only with a builtin-baseline. Without one, versioning is ignored.

Safeguard's SBOM and dependency scanning can build an inventory of the components in a repository, and the free scan at gold.safeguard.sh/scan is a quick way to see what turns up.

Sources

Last reviewed: 19 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.