License scanners miss vendored code and git submodules because they read package manifests and lockfiles, and copied directories or submodule pointers appear in neither. To close the gap, inventory those directories explicitly, scan their files directly, and record the upstream source and license for each.
Where the blind spots are
| Source of code | Why it can be missed |
|---|---|
| Copied library folder | No manifest entry |
| Git submodule | A pointer in the parent repo, content lives elsewhere |
| Vendor directory from a package manager | May be excluded by ignore rules |
| Single copied file or snippet | No package identity at all |
| Minified or bundled output | Original headers stripped |
File based detectors can also be limited. Go's package site documents that it only inspects files with names like LICENSE or COPYING and may fail on edited text, which shows the general weakness of name and text matching. See how Go license detection works.
Checks to add
- Search the repository for directories named vendor, third_party, external and lib, and for a gitmodules file.
- For each hit, identify the upstream project and version. If unknown, treat as unknown.
- Make sure your scanner is configured to include these paths. Many default ignore rules skip them. See SAST exclusions for vendored code for the related trade off on code scanning.
- Initialize submodules in CI before scanning, or the scan sees empty folders.
- Record each vendored component in the inventory with its license and upstream URL.
- Prefer a package manager dependency over a copy where you can, so updates and advisories are tracked.
Snippets
Copying a few lines from another project is the hardest case. A license may still apply. Teams usually handle it by policy: require a source note in the file and a review for anything beyond trivial lines. See copying code from Stack Overflow or a chat answer.
Security angle
Vendored code also hides vulnerabilities, because advisory matching relies on package identity. A copied library with a known flaw may never alert. Giving it an inventory entry solves both problems.
Try it yourself
Click through it at your own pace, or open it full screen.
Look at how components are identified, and consider what identity a copied folder would have.
A quick audit is to compare what your scanner reports with what a directory listing shows. Any top level folder of third party code that has no matching inventory row is a gap. Fix each gap by adding the component, or by replacing the copy with a managed dependency, and then add a CI check that fails when a new vendor folder appears without an inventory entry.
Safeguard scans dependencies and builds SBOMs. Run a free scan and compare it with what you know you vendor.
Quick check
Does scanning the parent repo include submodule contents?
Only if submodules are checked out in CI and the scanner is configured to read them.
Why does vendoring hide vulnerabilities?
Advisories match on package identity, and a copied folder has none.
Sources
- Go package discovery site, license policy: https://pkg.go.dev/license-policy
Last reviewed: 19 October 2026.