Software licensing focusing on open source
Objectives
Principles of open source licensing
Difference between permissive and copyleft licenses
Regulations for AI-generated and AI-assisted code
Determine the software license for your project following EU regulation
Navigate the Joinup Licensing Assistant to select a compliant license
Understand the licensing distinction between container recipes and container images
Limitations and context of this lesson
This lesson is designed as practical educational material for researchers and research software engineers, not formal legal advice
Regional Focus: Guidance is grounded in EU statutory directives, European institutional frameworks and developers based in Europe with a global focus.
Institutional Context: Employment contracts, grant agreements, and university policies heavily influence software ownership and licensing choices.
This lesson covers only the general principles of open-source reuse, copyright scope, and software adaptation.
If you need formal guidance references below and legal experts, especially if you have legal services at your host institute, could be of help:
Introduction: What is a Software License?
Under copyright law worldwide, software without an explicit license automatically defaults to All Rights Reserved: meaning nobody else has the legal right to run, modify, embed, or cite your code. A software license is a legal permission grant created by the author that overrides this statutory default, defining how downstream researchers can reuse your work.
In this lesson, we focus on open-source licenses to define both how we grant permissions for software we develop (outbound licensing) and how we safely comply with terms attached to code written by others (inbound reuse).
Open-source licenses fall into two main families:
Permissive (e.g., MIT, Apache-2.0, 0BSD): Do whatever you want, just keep crediti. Grants maximum reuse freedom, allowing anyone to modify, embed, or re-license your code in open or closed projects.
Copyleft/Reciprocal (e.g., GPL-3.0, EUPL-1.2): Share alike. Grants full freedom to run and modify, but mandates that any distributed derivative or combined work must also be released under matching copyleft terms. Often informally referred to as viral or infectious because its open-source requirements propagate across code boundaries (such as embedding snippets or static linking) into downstream projects. The diagram below unifies these license choices and their downstream rights:
Copyright Foundation: Expression vs. Ideas
To understand why licenses are required, you must understand how copyright law treats software. Under EU statutory law (Directive 2009/24/EC) and international treaties, software is protected under copyright as a literary work.
However, copyright law draws a sharp, fundamental distinction between what is protected and what is free for anyone to use:
Protected (Code Expression): The specific source code text, variable names, binaries, container build recipes, prompt engineering text, and preparatory design documents.
Not Protected (Underlying Ideas): Mathematical algorithms, scientific models, programming logic, data structures, and interface principles.
Because copyright restricts only the creative human expression and not the underlying ideas or algorithms, developers could use open-source licenses to define the exact terms under which that expression can be legally shared and modified.
Scope of this Lesson: What Counts as Software?
Across international legal frameworks (such as 17 U.S.C. § 101 and WIPO-World Intellectual Property Organization model provisions), software is broadly defined as a set of instructions to be used directly or indirectly in a computer to bring about a certain result.
Because modern research software extends beyond simple Python scripts, this lesson applies copyright and licensing principles across six core research software assets:
Source Code: Original algorithms written from scratch or implemented from scientific papers.
Third-Party Integrations: Embedded permissive or copyleft code snippets and linked libraries (dynamically/statically).
Infrastructure as Code: Ansible playbooks,Terraform configurations,container Recipes (
Dockerfile, Apptainer.def).Container Images: Bundled binary filesystem snapshots (
.siffiles, OCI registry images).AI-Assisted Code: Code generated, refactored, or assembled with human creative oversight.
AI Prompt Templates: Complex, engineered system prompts and structured frameworks meeting the threshold of human creative authorship.
Motivation: Debugging a License Compliance Failure
With the understanding of the difference between Permissive and Copyleft licenses, examine what happens when they collide inside an automated CI/CD pipeline:
Limitations of AI-Assisted Licensing Advice
Modern software developers and RSEs routinely rely on AI coding assistants (ChatGPT, Claude, GitHub Copilot) to generate boilerplate, refactor functions, and answer project setup questions.
However, using these tools for legal or licensing guidance introduces a subtle risk of AI legal bias as AI models are overwhelmingly trained on US-centric web data and legal forum posts, their outputs default almost universally to US common law concepts such as Fair Use, Work Made for Hire, and Derivative Works.
In contrast, developers operating under EU statutory frameworks (such as Directive 2009/24/EC) face a different legal reality related to exceptions, author ownership, and code adaptations. Relying blindly on AI legal advice creates significant compliance blind spots, which is why this lesson equips you with a direct, EU-aligned framework for software licensing.
Standardizing In-File Declarations: SPDX Identifiers
Selecting a license is only half the battle; automated scanners and CI/CD pipelines need a machine-readable way to verify license compliance per file without parsing long legal texts.
Managed by the Linux Foundation, SPDX identifiers (Software Package Data Exchange) provide standardized short tags (e.g., MIT, Apache-2.0, GPL-3.0-only, EUPL-1.2) placed at the very top line of every source file:
# SPDX-License-Identifier: MIT
# Copyright (c) 2026 Author Name <author@institute.eu>
Throughout the exercise scenarios below, look for the In-File Identification (SPDX) callouts to see how these tags apply directly to Python scripts, container recipes, and engineered prompt templates.
License Selection Decision Matrix & Scenario Index
To help you navigate open-source compliance, the matrix below serves as an upfront quick-reference summary and interactive index for the core licensing scenarios encountered in research software engineering.
Joinup Licensing Assistant (JLA)
Our decision framework is grounded in the European Commission’s JLA, which evaluates software assets across six criteria categories:
Can (Permissions)
Must (Obligations)
Cannot (Restrictions)
Compatible** (Interoperability)
Law (Jurisdiction)
Support(Governance)
Use this index to preview the demonstrated path for each scenario, or click any module link to jump directly to its detailed exercise, legal analysis, and JLA selection instructions.
Scenario Module |
Demonstrated Path / Focus |
Compliant Target Licenses |
|---|---|---|
🟢 Permissive (Default Choice) |
|
|
🟡 Copyleft / Reciprocal |
|
|
🟢 Permissive Focus (Copyleft Flexible) |
|
|
🟡 Mandatory Copyleft |
|
|
🟡 Mandatory Copyleft |
|
|
🟢 Permissive Focus |
|
|
⚠️ Multi-License Bundle |
Governed by individual layer/binary terms |
|
🟢 Permissive Focus (Author Choice) |
|
|
🟢 Permissive Focus |
|
Module 2: The Dependency Minefield – Inbound Code & Linking
Embedding third-party source code snippets or linking against strong copyleft libraries introduces legal boundaries that restrict your repository choices.
Module 3: Dependency Linking & Packaging
When software incorporates external dependencies, whether by dynamic linking, static compiling, or bundling binaries into container images licensing obligations expand beyond your own written source code. This module covers how dependency boundaries, build automation scripts, and packaged container artifacts affect legal compliance under the Joinup Licensing Assistant (JLA) framework.
Scenario 5: Linking against a GPL-licensed library
You are developing an software application that imports or links against an external software library licensed under GPL-3.0 (e.g., importing a GPL Python package or linking a C/C++ static/shared library).
Licensing Goal: Ensure legal compliance while using copyleft libraries as core dependencies in your software project.
Legal Reality: Under mainstream copyright interpretation and the text of GPL-3.0, linking your code directly against a GPL library (whether statically or dynamically) creates a combined work. Consequently, the copyleft obligations of the external library extend to your entire repository.
JLA Selection Strategy: Because linking to a GPL library requires your distributed project to be released under matching reciprocal terms, you must configure JLA to mandate source code disclosure (
Disclose source) and reciprocal licensing (Copyleft/Share a.).
Solution
What to select in the JLA interface:
Can Column: Select
Distribute,Modify/merge, andCommercial useMust Column: Select
Incl. Copyright,Disclose source, andCopyleft/Share a.Support Column: Select
OSI approved
Example JLA Matches:
GPL-3.0,EUPL-1.2Linking Boundaries & License Selection (Legal Nuance):
Why GPL forces copyleft: Linking against a standard
GPL-3.0library extends copyleft to your entire project. Your repository must adopt a compatible copyleft license (GPL-3.0orEUPL-1.2, which explicitly lists GPL-3.0 in its compatibility appendix).Why LGPL or EUPL-1.2 libraries allow permissive licenses: If the external library is licensed under
LGPL(which includes an explicit linking exception) orEUPL-1.2(where European Commission guidance takes the position that dynamically linking an EUPL work through its API does not by itself create a derivative work), copyleft does not extend to your application. In these dynamic linking scenarios, your own project can stay permissively licensed (e.g., MIT, Apache-2.0, BSD). However, note that this EUPL stance reflects Commission guidance rather than settled CJEU case law, and static linking or direct code incorporation continues to trigger EUPL copyleft obligations.
Downstream Obligations: Downstream users who receive or run your application must receive full access to your source code under
GPL-3.0(orEUPL-1.2), along with all upstream copyright notices and build scripts required to recompile the project.Allowed Inbound Code & Dependencies: Your project can import or include other permissively licensed packages (MIT, BSD, Apache-2.0) and public domain waivers (CC0). However, all code linked together in the final executable or runtime environment must satisfy GPL compatibility.
In-File Identification (SPDX): Apply standard machine-readable SPDX identifier comments directly at the top of your main scripts:
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (c) 2026 Author Name <author@institute.eu>
import gpl_licensed_solver # External GPL dependency forces GPL/EUPL compliance
def solve_system(data):
return gpl_licensed_solver.compute(data)
Scenario 7: Distributing pre-built container images
You compiled and published a pre-built container image (e.g., pushing a compiled Docker image to Docker Hub, GitHub Container Registry, or an institutional registry) containing an OS layer, runtime binaries, dependencies, and your application code.
Licensing Goal: Safely distribute compiled container images without violating the license terms of any software layer or binary included inside the image.
Legal Reality: A compiled container image is a multi-license aggregate bundle. Distributing pre-built binaries triggers source-code distribution obligations for any copyleft software (e.g., Linux base packages, coreutils, GPL libraries) pre-installed inside the image layers.
JLA Selection Strategy: Because a container image combines multiple distinct software components, JLA is used to evaluate constituent component obligations. When distributing compiled binaries containing copyleft layers, source disclosure requirements (
Disclose source) must be fulfilled for those specific layers.
Solution
What to select in the JLA interface:
Can Column: Select
DistributeandCommercial useMust Column: Select
Incl. CopyrightandDisclose sourceSupport Column: Select
OSI approved
Example JLA Matches:
Multi-License Bundle(Governed by constituent package terms)Multi-License Aggregation Nuance: Applying a permissive license (like MIT) to your application code inside the container does not override or erase the GPL/LGPL obligations of base system packages installed in
/usr/libor/usr/bin. Distributing the built image binary makes you a distributor of all installed packages.Downstream Obligations: You must ensure that downstream users can obtain the source code for copyleft components shipped inside the image, typically by publishing the
Dockerfileand build steps used to generate the image from public upstream sources.Allowed Inbound Packages: Before publishing an image binary, run automated compliance scanning tools (e.g., Syft, Trivy) to generate a Software Bill of Materials (SBOM) and verify that no non-redistributable or proprietary software is packaged inside.
In-File Identification (Metadata Annotations): Document the multi-license nature of the aggregate bundle using standard OCI (Open Container Initiative) image labels inside your Dockerfile:
# SPDX-License-Identifier: MIT
# Copyright (c) 2026 Author Name <author@institute.eu>
FROM ubuntu:24.04
LABEL org.opencontainers.image.authors="author@institute.eu"
# OCI Standard Image Annotations for Docker Hub Compliance
LABEL org.opencontainers.image.title="My Research Pipeline"
LABEL org.opencontainers.image.licenses="MIT AND GPL-3.0-or-later"
LABEL org.opencontainers.image.vendor="My Institute Name"
LABEL org.opencontainers.image.description="Includes Ubuntu 24.04 base layers (GPL/LGPL) and custom solver (MIT)"
COPY solver.py /app/solver.py
Module 4: Emerging Workflows & AI
AI-assisted development tools and machine learning models introduce unique legal challenges regarding copyright ownership, training data memorization, and behavioral restrictions. This module addresses how to license projects built with AI code generation tools and how to package research software that bundles AI models, weights, and datasets alongside source code.
Scenario 8: AI-assisted code generation
You used AI tools (e.g., GitHub Copilot, ChatGPT, Claude) to write functions, unit tests, or documentation for your research software repository.
Licensing Goal: Retain clear ownership and apply a permissive license (
MITorApache-2.0) to your repository without incurring hidden copyright infringement or copyleft obligations from code embedded during model training.Legal Reality: Unmodified AI-generated outputs lack human authorship and are generally not eligible for copyright protection under current EU and international legal standards. However, if an LLM reproduces a substantial copyrighted code snippet verbatim from its training data (memorization), that output snippet retains its original copyright and license obligations.
JLA Selection Strategy: To ensure maximum adoption and academic reuse for your overall codebase, require citation credit (
Incl. Copyright) while avoiding share-alike constraints (leavingCopyleft/Share a.unselected), supported by automated compliance checks.
Solution
What to select in the JLA interface:
Can Column: Select
Distribute,Modify/merge, andCommercial useMust Column: Select
Incl. CopyrightSupport Column: Select
OSI approved
Example JLA Matches:
MIT,Apache-2.0,BSD-3-ClauseAI Code Generation & Verification Nuance: Because non-human AI output cannot hold copyright, your copyright applies to the overall project structure, human-written logic, and creative choices. To protect your repository against accidental copyright infringement or copyleft contamination from AI memorization, turn on public code matching filters in your AI tools and run automated code-similarity scanners before releasing your repository.
Downstream Obligations: Downstream users must preserve your copyright notice for the repository. They are free to reuse, modify, and integrate your code into commercial or open-source projects.
Allowed Inbound Snippets: You can include permissively licensed code, public domain code (CC0), and AI-generated snippets that have been verified against verbatim training data duplication.
In-File Identification (SPDX): Apply standard machine-readable SPDX identifier comments directly at the top of your scripts:
# SPDX-License-Identifier: MIT
# Copyright (c) 2026 Author Name <author@institute.eu>
def filter_sensor_data(raw_readings: list[float]) -> list[float]:
"""Cleans raw sensor data (written with AI assistance and human review)."""
return [reading for reading in raw_readings if reading > 0.0]
Scenario 9: Packaging AI workflows, datasets, and model weights
You are developing research software that includes source code alongside trained machine learning model weights (.pt, .safetensors) and benchmark datasets.
Licensing Goal: Apply a clear dual-licensing strategy that makes both the software source code and the non-code assets (data, weights) open and reusable under appropriate legal frameworks.
Legal Reality: Standard open-source software licenses (MIT, GPL) are written specifically for source code and are legally ill-suited for datasets or neural network parameters. Under EU legal frameworks, datasets and model weights are governed by database rights (sui generis database protection) rather than traditional code copyright.
JLA Selection Strategy: Use JLA to select an OSI-approved open-source license for the executable code component (
Incl. Copyrightselected), while using Creative Commons licenses (e.g.,CC-BY-4.0orCC0) for the dataset and weight files.
Solution
What to select in the JLA interface:
Can Column: Select
Distribute,Modify/merge, andCommercial useMust Column: Select
Incl. CopyrightSupport Column: Select
OSI approved
Example JLA Matches:
MIT,Apache-2.0(for the code component)Code vs. Data/Weights & OpenRAIL Nuance: Never apply software licenses like GPL or MIT to raw datasets or model weights. Use CC-BY-4.0 or CC0 for non-code assets. Additionally, behavioral licenses (such as OpenRAIL) impose usage restrictions (e.g., prohibiting specific harmful uses), which means they do not qualify as OSI-approved open-source software and cannot be filtered via standard JLA open-source queries.
Downstream Obligations: Downstream users must cite your repository for the code (under your chosen software license) and give credit for the model weights and data under the corresponding Creative Commons license.
Allowed Inbound Assets: You may combine permissively licensed python code with CC-BY-4.0 datasets or open-weight models, provided the attribution files clearly separate code licenses from data/weight licenses.
In-File Identification (SPDX / Dual-Licensing Structure): Document the dual-licensing scheme in your root repository structure and script headers:
# SPDX-License-Identifier: MIT
# Copyright (c) 2026 Author Name <author@institute.eu>
#
# Note: Source code is licensed under MIT.
# Model weights in /models/ and datasets in /data/ are licensed under CC-BY-4.0.
import torch
def load_pipeline():
model = torch.load("models/climate_weights.safetensors")
return model
Best Practices: Attaching a License to Your Repository
Once you have selected a license using the JLA, you must officially attach it to your repository so automated scanners, package registries, and downstream researchers can verify your terms.
1. Adding the Root LICENSE File
Always place the full text of your chosen license in a plain-text file named LICENSE or LICENSE.txt at the root of your repository.
Exact Legal Text: Copy the standard text directly from spdx.org/licenses or choosealicense.com.
Copyright Header: Ensure you fill in the copyright year and copyright holder line at the top of the license text:
Copyright (c) 2026 [Author Name or Institution Name]
Do Not Edit Terms: Never modify the legal wording of standard licenses (e.g., removing clauses from GPL or MIT). Custom license edits create non-standard legal texts that compliance scanners cannot parse, defaulting your repository back to restricted status.
2. Documenting License Status in README.md
Add a dedicated License section near the bottom of your repository’s README.md file, along with a machine-readable badge:
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
[](https://opensource.org/licenses/MIT)
3. Automated Compliance with the REUSE Standard
For multi-asset research repositories containing code, data, container build recipes, and prompt templates, follow the FSFE REUSE Initiative standard:
Include License Texts: Place full license files inside a
LICENSES/directory (e.g.,LICENSES/MIT.txt,LICENSES/GPL-3.0-or-later.txt).Add In-File SPDX Headers: Label every source file, build script, and prompt file with SPDX tags.
Verify Compliance: Run the automated REUSE linter in your CI/CD pipeline:
# Install and run REUSE compliance check
pip install reuse
reuse lint
When reuse lint passes, downstream researchers can automatically verify the
legal status of every single asset in your codebase.
Summary: Resolving the Compliance Pipeline
When developing research software, license compliance is not an afterthought to debug at the end of a project, it is a proactive design choice. By using the Joinup Licensing Assistant (JLA) framework to align your repository license with your inbound dependencies from day one, your CI/CD pipeline passes cleanly on the first run.
The diagram below illustrates how selecting a compatible license upfront ensures your code passes automated compliance checks and results in a legally sound release:
Scenario Mapping Across the Pipeline
Handling Inbound Copyleft (Scenario 4 & Scenario 5): When you copy non-trivial copyleft code snippets (e.g., CC BY-SA from Stack Overflow or GPL snippets) or link directly against a GPL library, your overall project becomes a combined work. Selecting a compatible copyleft license upfront (
GPL-3.0orEUPL-1.2) satisfies the reciprocal sharing terms and allows the pipeline scanner to pass without conflict.Maintaining Permissive Defaults (Scenario 1 & Scenario 3): If you write original code or embed only permissively licensed snippets (MIT, Apache-2.0, BSD), selecting a permissive license (
MITorApache-2.0) grants downstream users maximum adoption freedom while preserving your citation credit.Packaging and Build Automation (Scenario 6 & Scenario 7): Keep plain-text build recipes (Dockerfiles) permissively licensed for maximum reuse, while annotating compiled container image binaries as multi-license aggregate bundles to satisfy embedded base-layer obligations.
AI Assets and Dual-Licensing (Scenario 8 & Scenario 9): Run code-similarity scanners to catch LLM training memorization before releasing AI-assisted code, and apply dual-licensing to separate executable software code (
MIT) from non-code datasets and model weights (CC-BY-4.0).Standardized Distribution: By adding machine-readable SPDX headers across every script, Dockerfile, and prompt template, running
reuse lintin your pipeline confirms 100% legal clarity for the entire scientific community.