An open source licence in a commercial product is a grant of rights with conditions attached. You must read the terms of every dependency you ship — direct and transitive — and confirm they match how you distribute and monetise the product. Attribution, copyleft and network-use clauses are the ones that cause trouble. Fix mismatches before release, not after.
Key Takeaways
- Distribution and network exposure create licence obligations; internal-only tools usually do not.
- Transitive dependencies cause most surprises, not the packages you deliberately chose.
- Permissive licences (MIT, BSD, Apache-2.0) mostly need notices kept. Copyleft terms can reach your combined work.
- A licence policy only counts if CI enforces it. A wiki page enforces nothing.
- Scan the built artefact and the container image, not just the repository — that is where dev-only packages hide.
- The cost of fixing a licence problem roughly tracks when you find it: hours in the sprint, months after launch.
- An SBOM you already produce for vulnerability scanning is the same inventory you need for licence review.
What does an open source licence actually grant you?
An open source licence grants copyright permissions on conditions. Permissive licences such as MIT and Apache-2.0 mostly require you to keep the copyright notice and, for Apache-2.0, the NOTICE file and patent-termination terms. Copyleft licences such as GPL-2.0, GPL-3.0 and AGPL-3.0 attach obligations to how you distribute or expose the software.
Those obligations are the whole argument. A licence does not care that most of your code is yours. Link a GPL library into a binary you ship and the terms can reach the combined work. Run an AGPL service and let users talk to it over a network and the terms can reach the source behind that service. Permissive terms rarely surprise anyone. Copyleft and source-available terms do.
Why does licensing bite in production rather than in code review?
Licence problems surface late because nothing fails. The build passes, the tests pass, the app ships. Exposure appears when a customer's procurement team runs a software composition scan, when an investor asks for a dependency report during due diligence, or when a rights holder sends a letter. Until then the risk sits quietly in a package nobody added on purpose.
Transitive dependencies are the usual culprit. A typical Node.js or PHP application pulls hundreds of packages, and the licence you need to read is often three levels down: a parser, a date library, a PDF renderer. We have seen a Laravel project where the only AGPL code in the tree arrived through a PDF-to-image helper added for one admin screen. Nobody chose it. It shipped anyway.
When do you actually need a licence audit, and when is it overkill?
You need a licence audit when you distribute software outside your own organisation, when you sell or host a product customers pay for, or when a buyer, investor or enterprise client asks for a software bill of materials. You can skip the formal exercise for internal tools that never leave your network, though AGPL and source-available terms still deserve a look.
The rule of thumb: distribution and network exposure create obligations, internal use usually does not. Shipping an Android or iOS app, selling a WordPress plugin, or letting customers log into a hosted portal all count. Running a script on your own laptop does not.
If the product is still a prototype nobody pays for, a full audit is overkill. Run a scanner, fix obvious copyleft in the shipped path, and revisit it before your first paid release. If you are selling into enterprise procurement, assume the questionnaire is coming and prepare for it early.
How do the main licence families compare?
Licences fall into four practical groups, plus a fifth that is not open source at all. Permissive terms let you ship closed source as long as you keep notices. Weak copyleft applies to changes in the library itself. Strong copyleft can reach the linked work. Network copyleft can reach hosted services. Source-available licences are contracts, not grants.
| Family | Examples | Main obligation | Where it usually fits |
|---|---|---|---|
| Permissive | MIT, BSD-2-Clause, Apache-2.0 | Keep copyright and licence text; Apache-2.0 also keeps NOTICE | Anywhere, including closed-source products |
| Weak copyleft | LGPL-3.0, MPL-2.0 | Share changes to the library; allow relinking | Dynamically linked libraries, plugin boundaries |
| Strong copyleft | GPL-2.0, GPL-3.0 | Offer complete corresponding source for the covered work | Separate processes, or accept the obligation |
| Network copyleft | AGPL-3.0 | Offer source to users interacting with it over a network | Isolated internal services, or avoid |
| Source-available | BSL, SSPL, vendor EULA | Whatever the contract states; often restricts competing use | Only with legal sign-off and a paid term |
How do you run a licence audit, step by step?
An audit is four passes: inventory every dependency, classify each licence, compare it against how you distribute, then remediate what fails. Automate the first two, because a manual list goes stale within a sprint. Do the third with someone who knows the product's distribution model.
- Generate an inventory from the lockfile, not from memory.
npm ls --all --json,composer licensesorgo list -m alleach give you something parseable. The lockfile captures what you actually resolved, including transitive packages. - Produce an SBOM (software bill of materials) in a standard format such as SPDX or CycloneDX, and store it per release. You will need it for customer questionnaires anyway.
- Classify against a written policy. Keep an allow-list of permissive licences, a review list, and a deny list — typically AGPL, SSPL and anything source-available — for code in the shipped path.
- Map each flagged component to its use. A GPL test runner is not the same as a GPL library linked into your binary. Linked code, a separate process, a build tool and a dev-only dependency carry different obligations.
- Remediate the real problems. Swap the package for a permissive alternative, isolate it behind a process boundary or an internal API, or rebuild the feature. Swapping is usually cheaper than the legal conversation.
- Gate it in CI so the next developer cannot quietly add a denied licence on a Friday afternoon.
None of this is destructive, but be careful with step 5: replacing a library changes runtime behaviour, so run the full test suite and a staging deploy before you push it to production. A licence fix that breaks payments is a worse week than the licence.
Which configuration and tooling actually matters?
The configuration that matters is a policy file CI can enforce, not a wiki page nobody opens. Declare the licence in your own package metadata, keep a LICENSE file at the repository root, and let a scanner read the lockfile on every pull request. Blocking the merge is what makes the policy real.
Three things are worth setting up: a declared license field in your package.json or composer.json so scanners can read your own terms; a CI job that fails on denied licences; and an SBOM stored alongside each release artefact. GitHub's dependency tooling surfaces licence metadata and alerts on your dependency graph, and the SPDX licence list is the reference most scanners normalise against. Names matter here — scanners match on SPDX identifiers, so a hand-written licence string will not match anything.
How do you verify the audit actually holds?
Verification is a rebuild, not a re-read. Check out the release tag, install from the lockfile, regenerate the inventory, and diff it against the SBOM you stored. Then scan the built artefact, not the source tree — bundlers and container images are where a dev-only dependency sneaks into production.
Two checks catch most drift. First, scan the final container image or application bundle; a package pulled in by a build step can still end up inside the image you push. Second, prove the gate fails when it should. Add a known denied licence to a throwaway branch and watch the pipeline go red. A gate nobody has tested is a gate that does not work.
What are the failure modes, and how do you debug them?
The classic failure is a clean repository and a dirty artefact: nothing in your direct dependencies is copyleft, yet a bundled file carries an unexpected licence header. The second is a stale SBOM that no longer matches the release. Both are found by scanning what you ship, not what you wrote.
- Scanner reports an unknown licence. Usually a package with no LICENSE file or a custom header. Read the project's own repository, not its metadata — metadata is a claim, not a contract.
- A package offers multiple licences ("MIT OR Apache-2.0"). You may choose, but choose deliberately and record the choice in the SBOM.
- The licence changed between versions. Pin the version, re-read the terms, and treat a major upgrade as a licensing change as well as a code change.
- Copyleft appears only inside the image. Check base images and OS packages from the distribution; redistributing the image can add obligations even when using the software locally would not.
- A dependency is dual-licensed commercially. That is a purchasing decision, not a code decision. Flag it early, before it blocks a release.
What does compliance cost, in effort and operational overhead?
The cost is engineer time, and it scales with when you find the problem. A scanner plus a policy file costs a few hours of setup and a few minutes per pull request. Reworking a shipped product because a core library is copyleft costs weeks, plus retesting, plus whatever the customer conversation costs you.
There is a second cost that is not about your own code. Some projects sell commercial licences for dual-licensed software, and some sell paid support. Both are legitimate and often cheaper than a rewrite. Terms and prices change, so confirm current figures with the vendor directly rather than trusting a blog post — including this one. If you want a sense of what engineering time costs before you commit, building custom versus buying off the shelf covers the trade-offs.
What about security and supply chain?
Licence review and security review share the same inventory. If you already produce an SBOM for vulnerability scanning, you have the data for licence classification. Keeping one pipeline for both is cheaper than running two, and it means a package swapped to fix a CVE gets its licence re-checked at the same time.
Common mistakes we see
- Reading only direct dependencies. Transitive packages are the usual source of copyleft.
- Trusting the
licensefield in package metadata. It is a claim, not the contract. - Assuming "open source" means "use it however I like". It means the terms in the licence file.
- Auditing once at kickoff and never again, then wondering why the SBOM no longer matches.
- Letting a generator or an AI assistant add dependencies unreviewed. It will happily pull in terms you would never have picked.
- Confusing "we publish our code" with "we are compliant". Publishing is not the same as meeting notice and source-offer conditions.
A realistic scenario
A software team builds a customer portal for an overseas client. Halfway through, they add a charting library for the reporting dashboard. The library is MIT. Its PDF export dependency is AGPL-3.0. The build is fine, the client is happy, and the portal goes live in the client's own cloud account.
Six months later the client runs a procurement security review and the scan flags AGPL in the deployed bundle. Their legal team asks whether the portal's source must be offered to end users. Nobody knows. The team spends two weeks reading terms and getting an opinion, then replaces the export path with a permissive renderer. The swap takes two days. The conversation, the delay and the customer's lost confidence take the rest. For a buyer-side view of the same problem, see our note on source code escrow for small businesses.
How do most teams handle this in practice?
There are three workable approaches. A CI-enforced policy is the cheapest and covers most products. A periodic manual review suits small teams with few dependencies and no enterprise customers. A commercial scanner with legal support suits regulated or high-value products where being wrong costs far more than the tooling. Pick one and write it down.
In short: inventory from the lockfile, classify against a policy, map each flagged package to how you actually distribute, fix what fails, and enforce the policy in CI. Scan the artefact, not the repository. Re-check on every release, because dependencies move under you.
People also search for
Licence questions rarely arrive alone. Teams searching for open source licence business guidance usually want to know what the build costs, who owns the accounts, and how much of it should be custom at all. These are the adjacent decisions we get asked about most often.
- What a web development quote should actually break down
- Custom software versus off-the-shelf: which one to pick
- Which accounts and credentials your business should own
- Running user acceptance testing without a QA team
- What a business reporting dashboard should actually show
- Setting up analytics that answer business questions
Licence review is the kind of work that is boring until it is expensive. If you would rather not do it alone, our team can help you inventory dependencies, write a policy your CI can enforce, and clean up what has already shipped — as part of our wider custom software development work. There are more answers on our frequently asked questions page, or you can talk to us directly and we will tell you honestly whether you have a problem.












0 comments
Be the first to share your thoughts.
Leave a comment
Replying to — cancel