Open Source License Compliance
Comprehensive guidance for open source license compliance before and during development.
When to Use This Skill
- •Evaluating open source dependencies for new projects
- •Checking license compatibility between packages
- •Understanding obligations for distribution
- •Creating attribution notices and NOTICES files
- •Establishing license policies for your organization
License Categories
Permissive Licenses
Allow use, modification, and distribution with minimal restrictions.
| License | Obligations | Commercial Use | Patent Grant |
|---|---|---|---|
| MIT | Attribution | ✓ | No |
| BSD-2-Clause | Attribution | ✓ | No |
| BSD-3-Clause | Attribution, no endorsement | ✓ | No |
| Apache-2.0 | Attribution, state changes, NOTICE | ✓ | Yes |
| ISC | Attribution | ✓ | No |
Copyleft Licenses
Require derivative works to use the same license.
| License | Copyleft Scope | SaaS Trigger | Distribution Obligations |
|---|---|---|---|
| GPL-2.0 | Strong | No | Source disclosure |
| GPL-3.0 | Strong | No | Source disclosure, anti-Tivoization |
| LGPL-2.1 | Weak (library) | No | Source for library, linking allowed |
| AGPL-3.0 | Strong + Network | Yes | Source disclosure on network use |
| MPL-2.0 | File-level | No | Source for modified files |
| EPL-2.0 | Module-level | No | Source for modified modules |
Weak Copyleft vs Strong Copyleft
text
Strong Copyleft (GPL): ┌──────────────────────────────────────────┐ │ Your Application (becomes GPL) │ │ ┌──────────────────────────────────┐ │ │ │ GPL Library (linked/included) │ │ │ └──────────────────────────────────┘ │ └──────────────────────────────────────────┘ Weak Copyleft (LGPL): ┌──────────────────────────────────────────┐ │ Your Application (any license) │ │ ↓ dynamic link │ │ ┌──────────────────────────────────┐ │ │ │ LGPL Library (LGPL remains) │ │ │ └──────────────────────────────────┘ │ └──────────────────────────────────────────┘
License Compatibility
Compatibility Matrix
text
Inbound License → Outbound License Compatibility FROM ↓ / TO → | MIT | Apache | BSD | LGPL | MPL | GPL | AGPL ---------------|-----|--------|-----|------|-----|-----|------ MIT | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ Apache-2.0 | ✗ | ✓ | ✗ | ✓ | ✓ | ✓* | ✓* BSD-3-Clause | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ LGPL-2.1 | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ | ✓ MPL-2.0 | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ✓ GPL-2.0 | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ GPL-3.0 | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ AGPL-3.0 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ ✓ = Compatible, ✗ = Incompatible * GPL-3.0 only (Apache-2.0 incompatible with GPL-2.0)
Common Compatibility Issues
| Issue | Example | Resolution |
|---|---|---|
| GPL + Proprietary | Using GPL library in closed source | Use LGPL alternative or open source |
| Apache + GPL-2.0 | Combining Apache-2.0 with GPL-2.0 | Upgrade to GPL-3.0 |
| AGPL + SaaS | Using AGPL in web service | Open source your code or use alternative |
| Conflicting Copyleft | GPL + EPL in same binary | Separate into distinct programs |
Obligation Analysis by Use Case
Internal Use Only
| License Type | Obligations | Tracking Required |
|---|---|---|
| Permissive | None | Minimal |
| Weak Copyleft | None | Minimal |
| Strong Copyleft | None (no distribution) | Minimal |
| AGPL | Source available if network service | Yes |
Distribution (Desktop/Mobile)
| License Type | Obligations |
|---|---|
| MIT, BSD, ISC | Include license/copyright in distribution |
| Apache-2.0 | Include license, NOTICE file, state changes |
| LGPL | Provide library source, allow relinking |
| GPL | Provide complete source code |
| MPL | Provide modified file source |
SaaS (No Binary Distribution)
| License Type | Obligations |
|---|---|
| Permissive | None (no distribution) |
| GPL, LGPL | None (no distribution) |
| AGPL | Must provide source to users |
License Compliance Implementation
.NET Dependency Analysis
csharp
// License scanning integration
public class LicenseComplianceChecker
{
private readonly IPackageMetadataProvider _packageProvider;
private readonly LicensePolicy _policy;
public async Task<ComplianceReport> AnalyzeProject(
string projectPath,
CancellationToken ct)
{
var packages = await _packageProvider.GetPackages(projectPath, ct);
var report = new ComplianceReport();
foreach (var package in packages)
{
var license = await _packageProvider.GetLicense(package, ct);
var evaluation = _policy.Evaluate(license);
report.Packages.Add(new PackageLicenseInfo
{
PackageId = package.Id,
Version = package.Version,
License = license.SpdxIdentifier,
LicenseUrl = license.Url,
Category = license.Category,
Status = evaluation.Status,
Obligations = evaluation.Obligations,
Issues = evaluation.Issues
});
}
return report;
}
}
public class LicensePolicy
{
private readonly HashSet<string> _approved = new()
{
"MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC"
};
private readonly HashSet<string> _requiresReview = new()
{
"LGPL-2.1", "LGPL-3.0", "MPL-2.0", "EPL-2.0"
};
private readonly HashSet<string> _prohibited = new()
{
"GPL-2.0", "GPL-3.0", "AGPL-3.0"
};
public PolicyEvaluation Evaluate(LicenseInfo license)
{
if (_approved.Contains(license.SpdxIdentifier))
{
return new PolicyEvaluation
{
Status = PolicyStatus.Approved,
Obligations = GetObligations(license.SpdxIdentifier)
};
}
if (_requiresReview.Contains(license.SpdxIdentifier))
{
return new PolicyEvaluation
{
Status = PolicyStatus.RequiresReview,
Obligations = GetObligations(license.SpdxIdentifier),
Issues = new[] { "Copyleft license requires legal review" }
};
}
if (_prohibited.Contains(license.SpdxIdentifier))
{
return new PolicyEvaluation
{
Status = PolicyStatus.Prohibited,
Issues = new[] { "Strong copyleft incompatible with proprietary distribution" }
};
}
return new PolicyEvaluation
{
Status = PolicyStatus.Unknown,
Issues = new[] { $"Unknown license: {license.SpdxIdentifier}" }
};
}
}
Attribution and NOTICE Files
csharp
// NOTICE file generator
public class NoticeFileGenerator
{
public string GenerateNotice(IEnumerable<PackageLicenseInfo> packages)
{
var sb = new StringBuilder();
sb.AppendLine("THIRD-PARTY SOFTWARE NOTICES AND INFORMATION");
sb.AppendLine("=============================================");
sb.AppendLine();
sb.AppendLine("This software includes the following third-party components:");
sb.AppendLine();
foreach (var pkg in packages.OrderBy(p => p.PackageId))
{
sb.AppendLine($"## {pkg.PackageId} ({pkg.Version})");
sb.AppendLine($"License: {pkg.License}");
sb.AppendLine($"URL: {pkg.LicenseUrl}");
sb.AppendLine();
if (!string.IsNullOrEmpty(pkg.Copyright))
{
sb.AppendLine(pkg.Copyright);
sb.AppendLine();
}
if (!string.IsNullOrEmpty(pkg.LicenseText))
{
sb.AppendLine("License Text:");
sb.AppendLine(pkg.LicenseText);
sb.AppendLine();
}
sb.AppendLine("---");
sb.AppendLine();
}
return sb.ToString();
}
}
.NET Project Configuration
xml
<!-- Enable license metadata in build --> <PropertyGroup> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> </PropertyGroup> <ItemGroup> <!-- Include NOTICE file in package --> <None Include="NOTICE.txt" Pack="true" PackagePath="" /> <!-- Set license expression for your package --> <PackageLicenseExpression>MIT</PackageLicenseExpression> <!-- OR for file-based license --> <PackageLicenseFile>LICENSE.txt</PackageLicenseFile> </ItemGroup>
License Policy Template
Organizational License Policy
markdown
# Open Source License Policy ## 1. Purpose This policy governs the use of open source software in [Organization] products. ## 2. License Categories ### 2.1 Approved Licenses (No Review Required) - MIT - Apache-2.0 - BSD-2-Clause - BSD-3-Clause - ISC - Unlicense - CC0-1.0 ### 2.2 Requires Review - LGPL-2.1, LGPL-3.0 (weak copyleft - usage context matters) - MPL-2.0, EPL-2.0 (file/module-level copyleft) - Creative Commons (varies by type) - Dual-licensed packages ### 2.3 Prohibited - GPL-2.0, GPL-3.0 (strong copyleft - unless project is GPL) - AGPL-3.0 (network copyleft) - SSPL (Server Side Public License) - Any license with field-of-use restrictions - Unknown or custom licenses without legal review ## 3. Process ### 3.1 New Dependency Addition 1. Check license using `dotnet-license-check` or equivalent 2. If Approved: Proceed, ensure attribution 3. If Requires Review: Submit to legal@company.com 4. If Prohibited: Find alternative or request exception ### 3.2 Distribution Before any release: 1. Run license audit 2. Generate NOTICE file 3. Include required attribution 4. Archive source code for copyleft compliance ## 4. Exceptions Exceptions require written approval from Legal and CTO. ## 5. Compliance Verification - Automated scanning in CI/CD pipeline - Quarterly manual audits - Annual policy review
SPDX Identifiers
Common SPDX Identifiers
text
Permissive: MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, Unlicense, CC0-1.0 Weak Copyleft: LGPL-2.1-only, LGPL-2.1-or-later, LGPL-3.0-only, LGPL-3.0-or-later MPL-2.0, EPL-2.0, OSL-3.0 Strong Copyleft: GPL-2.0-only, GPL-2.0-or-later, GPL-3.0-only, GPL-3.0-or-later AGPL-3.0-only, AGPL-3.0-or-later Compound Expressions: (MIT OR Apache-2.0) - Choice (LGPL-2.1-only AND MIT) - Both apply GPL-2.0-only WITH Classpath-exception-2.0 - Exception
CI/CD Integration
License Scanning Pipeline
yaml
# GitHub Actions example
name: License Compliance Check
on:
pull_request:
paths:
- '**/*.csproj'
- '**/packages.lock.json'
jobs:
license-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Install license checker
run: dotnet tool install --global dotnet-project-licenses
- name: Check licenses
run: |
dotnet-project-licenses -i . \
--allowed-license-types "MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause" \
--output license-report.json \
--output-type json
- name: Upload license report
uses: actions/upload-artifact@v4
with:
name: license-report
path: license-report.json
- name: Fail on prohibited licenses
run: |
if grep -q "GPL-" license-report.json; then
echo "::error::Prohibited license detected"
exit 1
fi
License Compliance Checklist
Pre-Development
- • Define license policy for project
- • Identify project distribution model (SaaS/desktop/library)
- • Determine outbound license for your code
- • Establish dependency review process
During Development
- • Check license before adding each dependency
- • Maintain attribution in NOTICE file
- • Document any exceptions
- • Run license scanning in CI
Pre-Release
- • Complete license audit
- • Generate final NOTICE file
- • Verify all attributions included
- • Archive source for copyleft compliance
- • Legal sign-off if required
Cross-References
- •SBOM:
sbom-managementfor dependency tracking - •Security:
security-frameworksfor secure supply chain - •Data Privacy: Consider data handling in dependencies