Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
C/C++ · Snippet Matching

Find vendored C/C++ code that has no package manifest to scan

Most SCA tools read a lockfile. C and C++ firmware, SDK drops, and board-support packages rarely have one — the code is copied into the tree, not installed by a package manager. O3's snippet engine reads the source itself: it tokenizes and fingerprints your codebase, matches it against a corpus of known open-source libraries, and tells you which library a vendored file actually came from.

The gap

Manifest-based SCA needs a manifest. Most C/C++ doesn't have one.

Snyk, Dependabot, and Syft all work the same way: read a package-lock file, resolve the dependency graph, check each entry against a vulnerability database. That works when your dependencies were installed by a package manager.

A lot of C/C++ code isn't. A vendored third_party/zlib/ directory, a silicon vendor's SDK drop, a board support package pinned to one SDK release, a bootloader nobody has rebuilt since launch — none of it has a lockfile. A manifest-only scanner sees nothing there at all, not even an empty result. It just never looks.

manifest-scanner.log
$ sca-scan --file=CMakeLists.txt
// No package manager detected for third_party/
Testing CMakeLists.txt...
✓ No vulnerable dependencies found
// third_party/zlib/ (vendored 2021, CVE-2022-37434)
// was never inspected — no manifest referenced it
How it works

Read the source, not the manifest

1. Tokenize and fingerprint

Every scanned C/C++ file is parsed and broken into overlapping token windows, fingerprinted with a winnowing algorithm — the same family of technique used by plagiarism detectors and Black Duck's own signature scanner.

2. Match against a known-library corpus

Fingerprints are checked against a corpus built from real open-source C/C++ projects. A match doesn't require an exact byte-for-byte copy — reformatted or partially modified vendored code still matches at the snippet level.

3. Resolve the real library, not just a hit

The same file often appears in many corpus projects that happen to vendor it too. O3 resolves which library the code actually is — using how much of that library is present, and how your own tree names the vendored directory — rather than reporting every project that also contains it.

Version mapping

Black Duck makes a person confirm every match. This is automatic.

Black Duck's own documentation is explicit about this: components found by snippet matching are "not automatically added to the BOM"— each match has to be individually reviewed and confirmed by a person before it counts. Their own blog goes further: signature-style matching "can lead to unintentional misidentifications," so "a human auditor is required to verify and correct the results," citing an audit with over 1,000 matches needing manual correction. That review burden is the exact complaint we hear most from teams who've tried snippet-based SCA at any real scale.

The reason a match needs confirming at all is a real, structural one: a short code fragment usually doesn't belong to only one library or one version. Most of a library's source is unchanged release to release, so a single matched file can honestly match a dozen versions at once. There's no lockfile to break the tie the way there is for manifest-based dependencies.

O3 resolves this without a review queue. Every matched file gives a lower bound — "unchanged since at least version X" — and the true version is the highest bound across every file that matched. Tested against 16 real vendored checkouts across three libraries, that method landed on the exact version in every case where the corpus held it, and correctly reported an honest range ("0.2.3 or later") rather than a wrong guess in the two cases where it didn't. On the same worked example, Black Duck's documented tie-break (KB rank, then earliest release date) and SCANOSS's (oldest match in the corpus) both land on the wrong, older version.

scan-rollup.log
$ o3 scan --type snippet
Matched fingerprints against corpus...
4,648 raw snippet matches found
// rolling up by resolved library + version —
// no review queue, no manual linking step
✓ 74 distinct component@version rows
written to /dependencies
// version-confirmed CVEs promoted to
// real SCA vulnerability rows automatically
dependency-finding.json
$ cat dependencies/madler-zlib.json
{
"resolved_library": "madler/zlib",
"version": "1.2.11",
"upstream_cves": [
"CVE-2018-25032", "CVE-2022-37434"
],
// queried by upstream repo, not package
// name — distro-package advisories excluded
}
CVE attribution

Upstream CVEs, not distro-package noise

Black Duck's own documentation states that snippet matches are excluded from vulnerability counts and reports entirely — positioned as a license-compliance feature, not a vulnerability one. Querying a resolved library and version by package name is also a real trap: a plain query for zlib 1.2.11 returns over 100 advisories, and every one of them is a Debian, Ubuntu, or Alpine distro-package advisory that doesn't apply to a vendored source copy at all.

O3 queries by the resolved upstream repository instead, which returns the library's own CVEs and nothing else — five real advisories for that same zlib copy, not 101 rows about a package manager it never used.

We're direct about the limit here too: only matches where the version resolves with confidence get promoted to a real vulnerability row your team triages. The rest stay visible on the dependencies page as an unconfirmed finding rather than get filed as a vulnerability we can't actually stand behind.

Where this stands today

What it does, and what it doesn't do yet

A snippet-matching engine has real, known failure modes. Here's where ours currently stands, stated plainly rather than left for you to discover during a trial.

Does today

Matches vendored C/C++ code against known open-source libraries at the snippet level, including partially modified or reformatted copies.

Resolves which library a matched file actually is, not just every project that also happens to contain it.

Resolves the vendored version automatically from the code itself, and rolls thousands of raw matches into a short list of dependency rows — no manual match-by-match review queue.

Attaches upstream, component-level CVEs to a resolved match — filtered to the library you vendored, not distro-package noise — and promotes version-confirmed ones to real vulnerability rows automatically.

Runs as an opt-in scan type alongside SAST, SCA, and secret scanning in the same pipeline.

Doesn't do yet

Version resolution for every match. The corpus records which project it saw a file in, not always which exact upstream release it came from — when the evidence only supports a lower bound, it's reported as a range, not promoted to a confirmed vulnerability.

Line-level confirmation that the specific vulnerable lines were the ones copied. Today's CVE attribution is component-level: "the library you vendored has these CVEs at this version," not "the vulnerable function itself is present."

Exact whole-file matching as a separate, faster path. Every match today goes through snippet-level fingerprinting, even for a file vendored byte-for-byte.

Reliable detection of vendored code whose identifiers have been renamed. Snippet fingerprints are sensitive to identifier text, so a renamed copy of a known-vulnerable file can go undetected.

Where it fits

For codebases a package-manager scanner can't see into

Firmware and embedded Linux

Board support packages, RTOS integrations, and driver code that arrive as a vendor drop with no build-time package manager involved.

Vendored source trees

A copy of zlib, OpenSSL, or a compression library checked directly into third_party/ rather than pulled by a package manager at build time.

SDK and toolchain drops

A silicon vendor's SDK, pinned to one release and never touched again, with its own bundled open-source code baked in.

Legacy C/C++ services

Code old enough to predate the project's current build system, where dependencies were copied in by hand and the history of what came from where has been lost.

See what's vendored in your own C/C++ codebase

Snippet matching runs as an opt-in scan type alongside O3's SAST, SCA, and secret scanning. Talk to us about running it on a real codebase.

Talk to us
FAQ

Questions,
answered.

Everything teams ask before rolling this out. Still stuck? Reach our team.

  • Snippet matching identifies open-source code by fingerprinting the source text itself rather than reading a package manifest. It tokenizes scanned files, generates fingerprints using a winnowing algorithm, and matches them against a corpus of known open-source projects. This lets it find code that was copied directly into a repository, such as a vendored C/C++ library, that a manifest-based scanner like Snyk or Dependabot has no way to see.
  • Manifest-based tools read a package-lock file to build a dependency graph. Most C/C++ firmware, board support packages, and SDK drops have no package manager involved at all: the code is copied directly into the source tree by a person, not installed by a build tool. A manifest-only scanner does not report an error on this code; it simply never looks at it, because there is no manifest entry pointing to it.
  • Black Duck’s own documentation states that snippet matches are excluded from vulnerability counts and reports, positioning snippet matching as a license-compliance feature rather than a vulnerability-detection one. O3 resolves the upstream library and version behind a snippet match and attaches CVEs filed against that specific upstream repository at the component level.
  • Not with O3. Black Duck’s own documentation states that components found by snippet matching are “not automatically added to the BOM” and each match must be individually reviewed and confirmed before it counts. O3 resolves the library and version automatically from the code itself and rolls thousands of raw matches into a short list of dependency findings, with no per-match review queue required.
  • SCANOSS attaches CVEs at the package level: once a snippet resolves to a component and version, it inherits every CVE ever filed against that version, without distinguishing a small matched fragment from the full library. O3 resolves which upstream library the code actually is before querying for CVEs, filtering out advisories for distro packages or other projects that happen to share a name.
  • Partially. Reformatted code and code with minor edits still matches, because snippet fingerprints tolerate small changes. Code whose identifiers (function and variable names) have been renamed is a known, current limitation: fingerprinting is sensitive to identifier text, so a renamed copy of a known-vulnerable file can go undetected today.
  • No. It runs alongside manifest-based SCA as a separate, opt-in scan type. Manifest-based scanning is still the right tool for dependencies that are actually installed by a package manager; snippet matching covers the vendored, no-manifest code that manifest-based tools cannot see at all.