Safeguard
Supply Chain•

Does CMake FetchContent hide dependencies from vulnerability scanners?

Libraries declared in CMake code have no lockfile entry, so manifest-based scans can miss them. How to list them and get them into your inventory.

Safeguard Security Team
3 min read

It can. A scanner that reads package manager manifests and lockfiles sees nothing for a library declared in a CMake file, because FetchContent_Declare is build code, not a dependency manifest. You close the gap by extracting those declarations and recording them in your SBOM.

Why it happens

Most dependency scanning starts from files whose job is to list dependencies. Conan and vcpkg have such files. CMake does not: the FetchContent module downloads and builds sources from Git, archives, Subversion or Mercurial as part of the main project, and the declaration sits inside ordinary build logic.

The result is a dependency with a name, a source and a version, but no manifest entry. An advisory for that library has nothing to match against.

How to find them

  1. Search for FetchContent_Declare, ExternalProject_Add and add_subdirectory in all CMakeLists.txt and .cmake files.
  2. For each one, note the library name, the URL or repository, and the pinned reference (hash, tag or branch).
  3. Look for libraries copied into folders like third_party or external. That is a related problem, covered in how to find vulnerabilities in vendored or copied code.
  4. Check git submodules too, since they hide from lockfile scans in the same way.
  5. Identify build-time tools fetched the same way, since they are part of your supply chain even if they never ship.

Record them so they can be matched

For each fetched library, write a record with these fields:

FieldExample
NameThe library as upstream calls it
VersionRelease the hash corresponds to
SourceRepository URL or archive URL
PinCommit hash or archive digest
OwnerThe team that updates it

Then add it to your SBOM as a component. The identifier matters: where no package manager type fits, a generic type with the upstream name and version is the usual fallback.

Keep the record from drifting

A hand-written list ages quickly. A cheap safeguard is a CI check that fails when a FetchContent declaration appears whose name is not in the record. That turns a new dependency into a conversation in code review rather than a surprise in an audit.

Try it yourself

Open the demo and see how a dependency inventory shows components and versions. Think about which entries would be missing if your CMake declarations were not included.

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

Quick check

Do vcpkg and Conan projects have the same gap?

Less so, since vcpkg.json and conan.lock list dependencies. Anything fetched outside them still needs recording.

Is it enough to pin hashes?

Pinning gives repeatability, not visibility. You still need the library in your inventory to check it against advisories.

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.