Skip to content

The Drift Log · Provenance, licensing and the paper trail

Auditing Vendored Source Trees for Dual-License Traps

25 October 2026 · 4 min read · 776 words · established

A wax seal resting on a page of hash digests

Standard package scanners miss dual-license risks in vendored directories. Here is how to audit structural headers and enforce provenance in CI.

When an engineer copies a directory out of an open-source project directly into a repository's vendor/ or internal/ path, they almost never copy the root LICENSE file with it. They grab the two utility files that solve their problem, commit them with a message like vendor crypto helpers, and move on.

The application compiles. CI passes. But the parent repository was dual-licensed: free under AGPLv3 for open projects, or commercial under a paid proprietary grant. The top-level repository manifest declared this restriction; the copied .ts or .go files merely had a three-line copyright banner with no SPDX identifier, or no header at all.

As explored in our doctrine on why vendoring code without a paper trail is unsecured debt, unmanaged code is an unhedged legal liability. When upstream manifests are stripped, dual-license traps become invisible to standard package scanners.

Why Package Scanners Miss Dual-License Traps

Most software composition analysis (SCA) tooling operates at the package manager boundary. It parses package.json, go.mod, Cargo.lock, or pom.xml. It resolves version strings against vulnerability and license databases, extracts the declared license field, and greenlights the build.

Vendored source code bypasses this entire mechanism. Once third-party code lives directly in your source tree:

  1. Package manifests are absent: The vendor directory rarely contains the upstream project's metadata files.
  2. License files are discarded: Root COPYING, LICENSE, or LEGAL.txt files from upstream are treated as clutter and omitted during the initial copy.
  3. Dual-license terms hide in comments: Dual-licensed projects often state their dual-licensing posture only in their repository documentation or main README, leaving individual file headers with either generic copyright lines or references to an external URL that changes over time.

Relying on dependency manifest parsers for vendored code creates a false sense of license compliance. The scanner reports zero violations because it finds zero managed dependencies in that directory. The liability remains embedded in the source.

The Mechanics of a Structural Header Audit

Resolving software provenance across vendored trees requires a structural header audit: an inspection of every unmanaged file, its comments, and its origin rather than its enclosing package metadata.

repo-root/
└── internal/
    └── telemetry/
        ├── client.go       <-- No header; copied from AGPL/Commercial upstream
        ├── buffer.go       <-- "Copyright 2021 Acme Corp" (No license tag)
        └── vendor.meta     <-- Missing: No recorded origin or commit hash

A structural header audit walks unmanaged source paths and enforces four invariants:

1. Mandatory Machine-Readable License Tags

Every vendored file must declare an explicit SPDX-License-Identifier header comment. If an upstream file does not provide one, the vendoring commit must place a sidecar metadata file (such as client.go.license or a directory-level provenance.json) explicitly defining the applicable license terms under which the code was retrieved.

2. Dual-License Trigger Detection

Dual-license schemes typically use trigger words in comment headers or accompanying notices. An audit must search vendored trees for phrases that signal non-permissive dual structures:

  • Dual license / Dual licensed
  • Commercial license available
  • GNU General Public License alongside Enterprise
  • SSPL / Server Side Public License
  • Commons Clause

When a match is found, the file cannot be cleared automatically. It requires human or automated verification against your organization's legal boundary to determine which half of the dual-license applies to your usage.

3. Upstream Origin Pinning

A header audit is only as reliable as the commit origin it tracks. If you cannot point to the exact upstream commit SHA from which the vendored code was pulled, you cannot prove which license applied at the time of ingest. Upstream projects change licenses between releases; pinning the precise commit establishes the legal boundary at import. For projects maintaining modified vendored trees, tracking upstream patch provenance in vendored git trees ensures that internal modifications remain cleanly separated from upstream dual-licensed bases.

Enforcing Provenance in CI

Once an audit identifies unmanaged files, license checking must become a gate in your continuous integration pipeline.

A minimal shell check or dedicated scanner should fail the build when an unmanaged source file enters the tree without an approved SPDX identifier or provenance sidecar:

#!/usr/bin/env bash
set -euo pipefail

## Fail if any vendored file lacks an explicit SPDX header or sidecar
UNLICENSED_FILES=$(find internal/vendor/ -type f \( -name "*.go" -o -name "*.ts" \) \
  -not -exec grep -q "SPDX-License-Identifier" {} \; -print)

if [ -n "$UNLICENSED_FILES" ]; then
  echo "Error: Unlicensed vendored files detected:"
  echo "$UNLICENSED_FILES"
  exit 1
fi

Integrating this check alongside automated detection of license conflicts in vendored code ensures that dual-license ambiguity is caught before code reaches production or distribution.

What to Do on Monday

  1. Locate your unmanaged code: Run a scan across your repository for internal directories containing copied third-party source (vendor/, src/external/, pkg/third_party/).
  2. Scan for dual-licensing signals: Search those directories for terms like dual, commercial, AGPL, SSPL, or Commons Clause inside comment blocks.
  3. Map files to upstream commit SHAs: For every vendored block, verify that you have a recorded commit hash and repository URL confirming the exact license terms present at that revision.
  4. Attach explicit SPDX identifiers: Place a .license file or machine-readable manifest alongside every unmanaged dependency to document the resolved licensing path.

Keep reading

Next in the log

The Strategic Master Library · written and reviewed under the house's own epistemic rules: nothing claimed that we cannot show.