The Drift Log · Provenance, licensing and the paper trail
Automated Detection of License Conflicts in Vendored Code
21 October 2026 · 3 min read · 550 words · inference

A repeatable, model‑independent scan of vendored code can flag license conflicts before SBOM generation.
The hidden risk in vendored code
Many teams copy a library into a vendor/ directory and forget to check its licence. The failure mode is a license conflict that surfaces only after the SBOM has been published. The conflict can invalidate the SBOM, force a costly re‑license, or expose the company to infringement claims. The problem is not the presence of vendored code; it is the lack of a verifiable provenance record before the code reaches the SBOM.
Scan the directory and assign licences
A reliable scan starts with a file‑by‑file licence lookup. The steps are:
- Walk the vendored tree.
- For each source file, read the first few lines for an SPDX identifier (
SPDX-License-Identifier:). - If no identifier is found, fall back to a heuristic that matches known licence header patterns.
- Record the result in a simple CSV:
path, licence, confidence.
#!/usr/bin/env bash
root=$1
echo "path,license,confidence"
find "$root" -type f \( -name "*.js" -o -name "*.ts" -o -name "*.c" \) | while read f; do
header=$(head -n 10 "$f")
if grep -q "SPDX-License-Identifier:" <<<"$header"; then
lic=$(grep "SPDX-License-Identifier:" <<<"$header" | cut -d: -f2 | tr -d ' ')
echo "$f,$lic,high"
elif grep -q "MIT License" <<<"$header"; then
echo "$f,MIT,medium"
else
echo "$f,UNKNOWN,low"
fi
done
The script produces a deterministic list of licences. The output can be version‑controlled, guaranteeing repeatability. The same approach can be wrapped in the typed TypeScript client (@shpbl/sdk) if you prefer a programmatic API – see the /sdk page for an example integration.
Flag incompatibilities against your policy
A licence conflict is only a conflict relative to a policy. Define a minimal matrix that captures the licences you allow to coexist. For example:
| Allowed with | MIT | Apache‑2.0 | GPL‑2.0 | |--------------|-----|------------|--------| | MIT | ✅ | ✅ | ❌ | | Apache‑2.0 | ✅ | ✅ | ❌ | | GPL‑2.0 | ❌ | ❌ | ✅ |
With the CSV from the scan, a short Python script can raise a failure for any row that violates the matrix.
import csv, sys
policy = {
"MIT": {"MIT", "Apache-2.0"},
"Apache-2.0": {"MIT", "Apache-2.0"},
"GPL-2.0": {"GPL-2.0"},
}
conflicts = []
with open(sys.argv[1]) as f:
for path, lic, _ in csv.reader(f):
if lic == "UNKNOWN": continue
allowed = policy.get(lic, set())
for other_path, other_lic, _ in csv.reader(open(sys.argv[1])):
if other_path == path: continue
if other_lic not in allowed:
conflicts.append((path, lic, other_path, other_lic))
if conflicts:
for c in conflicts:
print(f"Conflict: {c[0]} ({c[1]}) ↔ {c[2]} ({c[3]})")
sys.exit(1)
Running the script in CI aborts the build if a conflict exists. The failure is explicit: file X is GPL‑2.0 while the project permits only MIT or Apache‑2.0. This makes the problem visible before the SBOM is generated.
Tie the licence report to SBOM verification
An SBOM should never contain a component whose licence conflicts with the project policy. The workflow is:
- Run the licence scanner.
- Fail fast on any conflict (as shown above).
- If the scan passes, invoke the SBOM generator (see the related post on Automated SBOM Generation from Build‑Intent Proposals).
- Attach the licence CSV as an artefact to the SBOM record.
Because the licence report is produced by a model‑independent tool, the provenance is repeatable and can be audited later. The SBOM verification step simply checks that the attached licence artefact contains no rows marked low confidence or UNKNOWN. If it does, the verification fails and the release is blocked.
Monday’s concrete step
- Add the scan script to the repository root.
- Add a CI job that runs the script on the
vendor/folder, aborts on non‑zero exit, and publishes the CSV as a build artefact. - Run the job locally on Monday to confirm it produces a clean licence report for your current vendored code.
Doing this turns a folder of hope into a verifiable provenance record. It eliminates the hidden license conflict risk before the SBOM is created, and it gives you a repeatable audit trail for every line of vendored code. For a deeper dive into why missing provenance is a liability, see the pillar post /blog/vendoring-code-without-a-paper-trail-is-unsecured-debt.
Keep reading
Next in the log
- Auditing Vendored Source Trees for Dual-License Traps
Standard package scanners miss dual-license risks in vendored directories. Here is how to audit structural headers and enforce provenance in CI.
- Lock Dependency Versions to Preserve License Provenance
Pinning dependencies creates an immutable link between code and its license provenance, enabling reliable audits.
- Automated SBOM Generation from Build‑Intent Proposals
Linking Build‑Intent proposals to SBOM entries creates an immutable, auditable provenance chain for vendored components.
The Strategic Master Library · written and reviewed under the house's own epistemic rules: nothing claimed that we cannot show.