# How do we detect software license obligation changes between releases?

> Compare release SBOMs with a reviewed license inventory to flag dependency, license, and completeness changes before legal review turns into a spreadsheet chase.

Canonical URL: https://www.devobs.io/articles/qa-ge50-license-obligation-drift-between-releases/
By: Theo Morgan
Published: 2024-04-18T08:19:40.998Z
Updated: 2026-09-06T10:18:15.722Z
Section: Architecture

Treat license review input as a versioned release artifact, not a fresh export each time. This article recommends an artifact-first process: generate an SBOM for each release, normalize it into one approved inventory, and diff that inventory against the last approved release by package identity, license metadata, and your internal obligation class. That gives legal a short list of meaningful changes instead of a full spreadsheet, while still forcing review when metadata is missing, conflicting, or incomplete. [GitHub’s SBOM export documentation](https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/establish-provenance-and-integrity/export-dependencies-as-sbom) supports using exported SBOMs as an inventory input, and the [CycloneDX specification overview](https://cyclonedx.org/specification/overview/) shows the kind of dependency and completeness data a structured BOM can carry.

## What should the release artifact contain?

Store two layers. First, keep the raw SBOM exactly as generated. [GitHub’s SBOM export documentation](https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/establish-provenance-and-integrity/export-dependencies-as-sbom) says SBOMs can include versions, package identifiers, licenses, transitive paths, and copyright information in SPDX format. Second, create an approved inventory derived from that SBOM. In that normalized inventory, add fields such as package URL or ecosystem identifier, version, your own direct-versus-transitive classification, declared license metadata, collected notice or license-text references, and any manual override with reviewer and reason.

That separation matters because scanner output is evidence, not your final legal position. [CycloneDX](https://cyclonedx.org/specification/overview/) is useful here because its object model can represent components, dependency relationships, annotations, and compositions. The same overview says the dependency graph can represent both direct and transitive relationships, and compositions can describe completeness as complete, incomplete, incomplete first-party only, incomplete third-party only, or unknown. That is exactly the kind of structure you want when a release changes only through a transitive update or when inventory quality itself is part of the release decision.

## What should the diff compare?

Do not fail every version bump. Compare three things separately:

1. Package set drift: added, removed, or replaced components.
2. License metadata drift: recorded license information changed, became more complex, or moved from known to unknown.
3. Obligation-class drift: your internal mapping changed from permissive to notice-required, reciprocal, restricted, or blocked.

The key is semantic diffing. Two releases may differ at the package version level but have no obligation change. [The SPDX specifications page](https://spdx.dev/specifications/) establishes SPDX as an international open standard, which makes it a sensible normalization target for the license information you compare across releases.

## How do you normalize messy license data before diffing?

Build explicit rules and make them deterministic. Parse declared license data into your chosen normalized form when possible. If metadata is custom or missing, attach an override record rather than silently guessing. If scanners disagree, keep both raw findings but require one approved value in the normalized inventory.

Require the candidate’s normalized inventory and its diff against the last approved inventory before approving the exact release contents. Also block if the SBOM is marked incomplete, because the [CycloneDX specification overview](https://cyclonedx.org/specification/overview/) explicitly says compositions can describe BOM completeness. An incomplete inventory should not pretend to be final.

## What does a useful worked example look like?

Release 1.4 approved inventory:
- pkg:npm/a version 2.1.0, MIT
- pkg:npm/b version 5.0.0, Apache-2.0
- transitive pkg:npm/c version 1.2.3, BSD-3-Clause

Release 1.5 candidate inventory:
- pkg:npm/a version 2.2.0, MIT
- pkg:npm/b version 5.1.0, Apache-2.0 OR MIT
- transitive pkg:npm/d version 4.0.1, MPL-2.0
- pkg:npm/c removed

Your diff should report:
- a: version changed, no obligation drift.
- b: recorded license data changed; review whether your chosen compliance path changes.
- c removed: obligations may disappear from future notices, but verify they remain covered in the shipped 1.4 rollback artifact.
- d added transitively: new review item, because package-set drift introduced a dependency your policy has not previously approved.

That is a legal review queue of three items, not hundreds of unchanged lines.

## How should the release gate and audit trail work?

Persist the last approved inventory with a content hash for the release build. For a candidate release, generate the new SBOM, normalize it, diff it, and open review tasks only for semantic drift. Record every override and reviewer decision in the approved inventory so the next release inherits resolved ambiguities instead of rediscovering them.

## Follow-up Q&A

**What if different build paths produce different SBOMs?**
Treat that as a boundary error, not noise. Approve the SBOM generated from the build path that produces the shipped artifact, and fail if another packaging path is released without its own inventory.

**What about monorepos with partial releases?**
Scope the inventory to the releasable unit and its shipped dependencies. A monorepo-wide SBOM is useful context, but the approval artifact must match the exact component being released.

Next step: add a normalized license inventory file to your release pipeline, store the last approved version, and make semantic diff review mandatory before tagging the release.

Reviewed: 2026-09-06

## Source references

- <https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/establish-provenance-and-integrity/export-dependencies-as-sbom>
- <https://cyclonedx.org/specification/overview/>
- <https://spdx.dev/specifications/>
