Open source license compliance for engineering teams
Five licenses every engineer should recognize
MIT
The most permissive widely-used license. Do almost anything with the code as long as you include the original copyright notice. No warranty, no liability.
Apache 2.0
Permissive like MIT but adds an explicit patent grant. Contributors give you a license to any patents covering their contribution. Includes a patent retaliation clause.
GPL v3
Strong copyleft. Any derivative work must be released under the same license. If you link GPL code into your application, the entire application must be GPL.
LGPL
Weak copyleft. You can link LGPL libraries into proprietary software without triggering copyleft, as long as users can swap the library. Modifications to the library itself must stay LGPL.
AGPL
The strongest copyleft license. Extends GPL to network use — if users interact with your software over a network, you must offer them the source code. Impacts SaaS deployments.
What each license actually requires
Four steps to systematic license compliance
Inventory
Catalog every open source dependency in your project — direct and transitive. You cannot comply with licenses you don't know about.
Classify
Map each dependency to its license type. Flag copyleft licenses, commercial restrictions, and any "unknown" or custom licenses for legal review.
Validate
Check that your usage pattern is compatible with each license. Linking a GPL library into a proprietary binary is a different risk than using an MIT utility.
Automate
Integrate license scanning into your CI/CD pipeline. Block builds that introduce non-compliant dependencies. Generate attribution notices automatically.
Tools for automated compliance
Snyk Open Source
Scans dependencies for license issues alongside security vulnerabilities. Integrates with GitHub, GitLab, and CI/CD pipelines. Provides policy-based gating.
FOSSA
Deep license analysis with support for complex dependency trees. Generates attribution reports and SBOM documents. Handles multi-language monorepos.
Mend (formerly WhiteSource)
Real-time dependency tracking with automated policy enforcement. Covers license compliance, security, and operational risk in a single platform.
license-checker (npm)
Lightweight CLI tool for Node.js projects. Lists all dependency licenses in a consumable format. Good for quick audits and CI integration without a SaaS dependency.
GitHub Dependency Graph
Built into every GitHub repository. Shows direct and transitive dependencies with license information. Free, zero-setup, and useful as a first line of defense.
Open source compliance checklist
Run through these items before every release to ensure your open source usage is documented, approved, and legally sound.
SBOM generation and management
SBOM Formats: SPDX vs CycloneDX
Two standards dominate. SPDX (Software Package Data Exchange), maintained by the Linux Foundation, is an ISO standard (ISO/IEC 5962:2021) with deep license metadata support. CycloneDX, from the OWASP community, started with a security focus and excels at vulnerability correlation. Both support JSON and XML output. For license compliance specifically, SPDX has richer license expression syntax — it can represent complex conditions like “MIT OR Apache-2.0” or “GPL-3.0-only WITH Classpath-exception-2.0” natively. For security-focused use cases, CycloneDX integrates more tightly with vulnerability databases.
Our recommendation: generate both. Tools like Syft and Trivy can produce SBOMs in either format from the same scan. Store them as build artifacts alongside your release binaries so they are always available for audit.
Integrating SBOM Generation into CI/CD
The SBOM must be generated at build time, not as an afterthought. Add a pipeline step after your dependency resolution (npm install, pip install, mvn dependency:resolve) that runs an SBOM generator against the resolved dependency tree. Tools like Syft can scan container images, file systems, and lock files. For Node.js projects, running “syft dir:. -o spdx-json” against the project root captures both direct and transitive dependencies. Store the output as a pipeline artifact with the same version tag as the release. Diff the SBOM against the previous release to surface newly added dependencies for review.
License compatibility: common combinations that trip teams up
MIT + Apache 2.0
Fully compatible. Both are permissive. You can combine them in the same project and distribute under either license (or a proprietary one). The only requirement is including both copyright notices and the Apache NOTICE file if one exists.
MIT + GPL v3
Compatible in one direction only. You can include MIT-licensed code in a GPL project (the combined work is GPL). You cannot include GPL code in an MIT project without relicensing the entire project under GPL. This is the most common source of accidental license violations in JavaScript ecosystems, where a single transitive dependency can pull in a GPL library three levels deep.
Apache 2.0 + GPL v2
Incompatible. The Apache 2.0 patent retaliation clause conflicts with GPL v2's terms. This was resolved in GPL v3, which is compatible with Apache 2.0. If you encounter a GPL v2-only dependency alongside Apache 2.0 code, you have a genuine legal conflict that requires either replacing one of the dependencies or obtaining a separate license.
LGPL + Proprietary (Dynamic Linking)
This is the scenario LGPL was designed for. If your proprietary application dynamically links to an LGPL library (shared library, DLL, or separate process communication), you do not trigger copyleft on your application code. However, you must allow users to replace the LGPL library with a modified version. In practice, this means distributing the LGPL component separately and documenting how to swap it. Static linking into a single binary triggers the copyleft clause.
AGPL in SaaS Deployments
This is the license that catches SaaS companies by surprise. If you use an AGPL library in a service that users interact with over a network, you must offer them the complete source code of the service — including your proprietary code. MongoDB's move from AGPL to SSPL and Elasticsearch's license change were both responses to cloud providers using AGPL-licensed software without contributing back. Treat any AGPL dependency as a hard blocker for proprietary SaaS unless legal counsel explicitly approves the usage.
Contribution policies and CLA management
Contributor License Agreements (CLAs)
A CLA is a legal document that contributors sign before their code is accepted into a project. It typically grants the project maintainer a license to use, modify, and redistribute the contribution. For corporate-maintained projects, CLAs protect against situations where a contributor later claims copyright over code embedded in your product. Tools like CLA Assistant (GitHub App) and EasyCLA (Linux Foundation) automate the signing process by checking every pull request author against a signed-contributor list.
Developer Certificate of Origin (DCO)
A lighter-weight alternative to CLAs. The DCO is a per-commit sign-off (git commit -s) where the developer certifies they have the right to submit the code under the project's license. Kubernetes, the Linux kernel, and many CNCF projects use DCO instead of CLAs. It is less legally robust than a CLA but creates less friction for contributors. For most corporate open source projects, DCO is sufficient unless your legal team requires explicit IP assignment.
Internal Contribution Policy
Your engineers will contribute to open source projects — either officially or on their own time. Without a policy, you risk employees accidentally contributing proprietary code to public repositories. A good internal policy covers: which projects employees can contribute to without approval, what approval process applies for contributions to projects that compete with your products, whether contributions made on company hardware or during work hours are company IP, and who reviews contributions before they are submitted to external projects. Document this policy and make it part of onboarding.
Beyond licensing: securing the software supply chain
Dependency Pinning and Lock Files
Never allow floating version ranges in production. Pin every dependency to an exact version and commit lock files (package-lock.json, Pipfile.lock, go.sum) to version control. This ensures that a build on Monday produces the same binary as a build on Friday, even if a dependency publishes a compromised update in between. Enable lockfile-only installs in CI (npm ci, pip install --require-hashes) to guarantee reproducibility.
Provenance Verification
SLSA (Supply-chain Levels for Software Artifacts) is a framework for verifying that a package was built from the source code it claims. npm now supports provenance attestations that link a published package to a specific GitHub Actions workflow and commit. Sigstore provides keyless signing for artifacts. Integrate provenance checks into your pipeline to verify that dependencies were built by their claimed maintainers, not by an attacker who compromised a maintainer's account.
Private Registry Mirroring
For high-security environments, mirror approved packages to a private registry (Artifactory, Nexus, or GitHub Packages). Engineers pull dependencies from the mirror, not the public registry. New packages enter the mirror only after passing license scanning, vulnerability checks, and — for critical dependencies — manual code review. This adds friction, but it eliminates the risk of typosquatting attacks and compromised public packages reaching production.
Maintainer Risk Assessment
A critical dependency maintained by a single volunteer is a supply chain risk regardless of its license. Evaluate dependencies not just for license compliance but for maintenance health: How many active maintainers? Is there a security disclosure process? When was the last release? Is the project backed by a foundation or company? Tools like Socket.dev and deps.dev surface these signals. For dependencies with a single maintainer and no funding, consider contributing engineering time or budgeting for sponsorship — it is cheaper than the incident response when the maintainer disappears.