GPL License
The GPL license is a strong copyleft license: use, modify, and sell freely, but distributing GPL code means releasing the whole program's source under the GPL.
Also known as GNU GPL, GNU General Public License, General Public License, GPLv2, GPLv3, GPL-2.0-only, GPL-2.0-or-later, GPL-3.0-only, GPL-3.0-or-later, LGPL, GNU Lesser General Public License, LGPLv2.1, LGPLv3
The GPL license (GNU General Public License, usually GPLv2 or GPLv3) is a strong copyleft license. It lets anyone run, modify, and sell software on one condition: whoever distributes the program, or a larger program built from it, must license the whole work under the GPL and provide its complete source code. The LGPL is its weaker library variant.
The GPL governs distribution, not use. Running GPL code on your own servers, modifying it privately, or using it across your company triggers nothing. Shipping it to someone else does, whether as a download, a desktop or mobile app, a container image a customer runs, or firmware. So the useful question for an engineering team is not "do we use GPL code?" but "does GPL code leave our hands, and inside what?"
Our position: the GPL exposure that catches teams today is rarely a library someone chose. It is a prebuilt binary inside a package whose metadata names a different license. The npm package ffprobe-static declares MIT, was downloaded 439,619 times in the week of October 19 to 25, 2026 (npm API), and ships six ffprobe binaries that each report "GPL version 3 or later." A GPL policy should key on how code leaves your hands, and it should be checked against what is inside each package version, not the license string in its manifest.
What is the GPL license?
#The GPL license is a copyright license that grants broad permissions and attaches one condition to redistribution: give recipients the same freedoms and the source. It is the best-known copyleft license, written by the Free Software Foundation (FSF). GPLv1 appeared in 1989, GPLv2 in June 1991, and GPLv3 on 29 June 2007.
Start with the default. Copyright gives an author the exclusive right to copy, modify, and distribute a program. Without a license you have none of those rights. The GPL grants all of them, conditionally. GPLv3 does not even ask you to accept it to use the software. Section 9 says: "You are not required to accept this License in order to receive or run a copy of the Program." Acceptance only matters when you do something that would otherwise infringe copyright, such as distributing copies.
GPLv3 makes the trigger precise with two defined verbs. To "propagate" is to do anything that needs copyright permission, except running the program or modifying a private copy. To "convey" is to propagate in a way that lets others receive copies. GPLv3 Section 2 then draws the line: "You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force." Section 0 closes the obvious question about servers: "Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying." That gap is the reason the AGPL license exists. GPLv2 uses the word "distribute" to the same effect.
When you do convey a GPL program, three duties follow:
- License the whole work under the GPL. GPLv3 Section 5(c): "You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy."
- Provide the Corresponding Source. GPLv3 defines it as all the source needed to generate, install, run, and modify the object code, "including scripts to control those activities." GPLv2 Section 3 says the same thing as "the scripts used to control compilation and installation of the executable." Build scripts are part of the deal.
- Keep notices and include the license. Section 4 requires copyright notices, the no-warranty notice, and a copy of the license with every copy.
Source can travel with the binary, sit behind a written offer valid for at least three years, or be offered from the same place you serve the binary. Nothing in the GPL limits price. Section 4: "You may charge any price or no price for each copy that you convey."
Where the GPL boundary falls
#The GPL boundary falls at the edge of "the work," and the license text does not define that edge in engineering terms. GPLv2 Section 2 says the conditions reach "the modified work as a whole," but not "identifiable sections" that "can be reasonably considered independent and separate works." GPLv3 Section 5 adds the aggregate rule: separate programs that merely share "a volume of a storage or distribution medium" do not pull each other under the GPL.
The FSF, which writes the license, interprets the edge by communication mechanism. In its GPL FAQ, linking a GPL module "statically or dynamically" with other modules makes a combined work, and the GPL covers "the whole combination." Code in the same executable or designed to share an address space is generally one program. Programs that talk through exec, pipes, sockets, or command-line arguments are generally separate, unless the data they exchange is intimate enough to make them one program. Interpreted languages follow the same rule: a GPL interpreter does not reach the scripts it runs, but a Python or JavaScript program that imports a GPL module shares its address space.
The figure, in text. Your code, combined with a GPL component, falls into one of three cases. First, same process: you import a GPL module, or link a GPL library statically or dynamically. The FSF treats this as one combined work, and if you convey it, the whole program goes out under the GPL with its source. Second, an LGPL library linked dynamically: your application keeps its own license, and you must let users replace the library with a modified version and relink. Third, a separate process: your program launches a GPL program with exec or talks to it over a pipe or socket. That is usually an aggregate, so only the GPL program carries GPL duties, and your program keeps its license. In every case, nothing applies until you convey a copy.
That boundary is the FSF's reading, and we know of no court ruling that settles whether dynamic linking alone creates a derivative work. Some projects remove the ambiguity themselves. The Linux kernel's syscall exception, which its top-level COPYING file applies to the whole kernel, carries a note from Linus Torvalds: "This copyright does *not* cover user programs that use kernel services by normal system calls" (Linux-syscall-note). The kernel also enforces its boundary in code. A module that declares MODULE_LICENSE("Proprietary") taints the kernel when loaded, and the module loader refuses to link it against symbols exported with EXPORT_SYMBOL_GPL().
Can you use GPL code in commercial software?
#You can use GPL code in commercial software, and you can sell GPL software itself. The FSF's FAQ answers the money question with "Yes, the GPL allows everyone to do this." What the GPL license forbids is conveying a combined work under proprietary terms. Whether a given product crosses that line depends on how the GPL code leaves your hands:
| Scenario | Conveying a copy? | What you owe under the GPL |
|---|---|---|
| Run GPL software on your own servers, such as a SaaS backend | No | Nothing. AGPL code is different: it adds a network trigger. |
| Run GPL tools internally, used only by employees | No | Nothing. GPLv3 Section 2 also lets contractors modify or run it on your behalf. |
| Ship a desktop, Electron, or mobile app that imports or links GPL code | Yes | License the whole app under the GPL and provide its Corresponding Source. |
| Ship an app that launches a separate GPL executable | Yes, the GPL program | GPL terms and source for that program. Your own code keeps its license. |
| Ship a container image or on-premises appliance to customers | Yes | GPL terms and source for every GPL component inside it. |
| Ship a consumer device running GPLv3 software | Yes | Source plus Installation Information so owners can install modified versions (GPLv3 Section 6). GPLv2 has no such rule. |
| Sell copies of an unmodified GPL program | Yes | License text, notices, and source. Any price is allowed. |
Teams that want GPL functionality in a proprietary product have five options, and each one costs something:
- Keep it on the server. Software you run but never convey carries no GPL duties. This stops working the day the product ships on-premises, as a desktop app, or as an image customers run, and it never works for AGPL code.
- Keep it at arm's length. Ship the GPL program as a separate executable and drive it through command-line arguments or a pipe. You still owe GPL terms and source for the GPL program you convey, but not for your own code. The FSF calls a main program that only invokes another program's main function and waits for it a borderline case, so design the interface to be cleanly separable.
- Prefer the LGPL. An LGPL library linked dynamically lets your application keep its license, as described below.
- Use an exception or buy different terms. Some GPL projects add a linking exception or sell commercial licenses alongside the GPL. MySQL introduced the MySQL FOSS License Exception in 2004, and PyPI still lists mysql-connector-python as "GNU GPLv2 (with FOSS License Exception)." The cost is reading the exception's conditions closely, or paying and tracking a renewal.
- Replace it. A permissive license alternative removes the question. The cost is engineering time and, often, features.
This is engineering guidance, not legal advice. We are engineers, not your lawyers, and a real combined-work question deserves a lawyer looking at your specific architecture.
What is the difference between GPLv2 and GPLv3?
#GPLv3 keeps GPLv2's copyleft and adds explicit patent licenses, anti-tivoization rules, a cure period for violations, and one-way compatibility with the Apache License 2.0.
| Topic | GPLv2 (June 1991) | GPLv3 (29 June 2007) |
|---|---|---|
| What triggers obligations | Distributing copies | Conveying copies; network interaction without a copy is explicitly excluded (Section 0) |
| Patents | No explicit patent grant | Each contributor grants a patent license (Section 11); discriminatory patent deals are restricted |
| Locked-down devices | No rule | Installation Information required for consumer User Products, unless no one can install modified code, such as code in ROM (Section 6) |
| Anti-circumvention (DRM) laws | Not addressed | Licensors waive the power to forbid circumvention of technological measures (Section 3) |
| Violations | Automatic, permanent termination (Section 4) | Reinstated if a first violation is cured within 30 days of notice, or if no notice comes within 60 days of stopping (Section 8) |
| Extra permissions and terms | Ad hoc exceptions | A formal framework for additional permissions and terms (Section 7) |
| Apache License 2.0 code | Incompatible | Can be included, in one direction |
| Source delivery | With the binary, or a written offer valid for three years (Section 3) | Adds network server and peer-to-peer options (Section 6) |
| Verdict | Use only when joining a GPLv2-only project such as the Linux kernel | Default for new GPL projects, as GPL-3.0-or-later |
The two versions are not compatible with each other by themselves. The FSF's license list says: "GPLv2 is, by itself, not compatible with GPLv3." Most GPLv2 code escapes that trap through the "or later" clause described in the next section. GPLv2-only code, the Linux kernel above all, cannot. Apache-2.0 code has the same split: the Apache Software Foundation's compatibility page says Apache 2 software "can therefore be included in GPLv3 projects," while "the FSF has never considered the Apache License to be compatible with GPL version 2."
GPLv3's termination design has won converts even among GPLv2-only projects. In 2017, Linux kernel developers added the Linux Kernel Enforcement Statement, adopting GPLv3's 30-day and 60-day reinstatement provisions "as additional permissions" for the kernel. The kernel stays GPLv2-only, but a first-time violator now gets the same chance to cure that GPLv3 gives.
Our verdict for authors: choose GPL-3.0-or-later for a new GPL project unless you are contributing to a GPLv2-only ecosystem. GPLv3's patent grant and cure period protect contributors and users, and Apache-2.0 compatibility widens what you can combine with. For consumers, the version matters most in two places: device makers, who owe Installation Information only under v3, and anyone combining GPL code with Apache-2.0 code, which works only under v3.
The "or later" clause and SPDX identifiers
#The "or later" clause is a GPL term that lets a recipient follow the named GPL version or any later version the FSF publishes. GPLv2 Section 9 and GPLv3 Section 14 define it, and the choice belongs to the recipient. Code under GPL-2.0-or-later can therefore be combined with GPLv3 or Apache-2.0 code by taking it under GPLv3. Code under GPL-2.0-only cannot.
The clause has a default that surprises people. GPLv2 Section 9 ends: "If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation." A package that just says "GPL" has, read literally, offered you every version back to GPLv1.
SPDX identifiers encode the difference: GPL-2.0-only, GPL-2.0-or-later, GPL-3.0-only, GPL-3.0-or-later. The older bare identifiers, GPL-2.0 and GPL-3.0, are deprecated in the SPDX License List (version 3.29 as of October 2026) because they do not say which. Old habits persist even in the most careful projects. The Linux kernel's own top-level license file still declares GPL-2.0 WITH Linux-syscall-note and spells out "version 2 only" in prose. The kernel's MODULE_LICENSE("GPL") tag, per its license rules, "does not express any distinction between GPL-2.0-only or GPL-2.0-or-later."
Registry metadata shows the full range. We pulled the current release of five GPL-family Python packages from PyPI's JSON API on October 27, 2026:
$ for p in pylint ansible-core PyQt6 paramiko mysql-connector-python; do
curl -s "https://pypi.org/pypi/$p/json" | jq -c '.info | {name, version,
license_expression, license,
classifiers: [.classifiers[] | select(startswith("License"))]}'
done
{"name":"pylint","version":"4.1.3","license_expression":"GPL-2.0-or-later","license":null,"classifiers":[]}
{"name":"ansible-core","version":"2.21.5","license_expression":"GPL-3.0-or-later","license":null,"classifiers":[]}
{"name":"PyQt6","version":"6.11.0","license_expression":"GPL-3.0-only","license":null,"classifiers":[]}
{"name":"paramiko","version":"5.1.0","license_expression":"LGPL-2.1","license":null,"classifiers":[]}
{"name":"mysql-connector-python","version":"26.10.0","license_expression":null,"license":"GNU GPLv2 (with FOSS License Exception)","classifiers":["License :: OSI Approved :: GNU General Public License (GPL)"]}Three of these are precise. paramiko uses a deprecated identifier that leaves "only" or "or later" open. mysql-connector-python uses free text, plus a trove classifier that names the GPL with no version at all. Our license analysis write-up calls many of those PEP 301 classifiers "irreconcilably ambiguous." Treat any GPL string without "-only" or "-or-later" as unresolved until a person reads the license headers in the source.
What is the LGPL, and how is it different from the GPL?
#The LGPL (GNU Lesser General Public License) is the GPL with additional permissions that let a proprietary program use an LGPL library, provided users can swap in a modified version of that library. LGPLv3 says so in its first sentence: it "incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below."
The key permission is Section 4, "Combined Works." You may convey your application linked with the library "under terms of your choice," as long as those terms do not restrict modifying the library or reverse engineering to debug such modifications. You must also do one of two things. Either use "a suitable shared library mechanism," meaning dynamic linking against a copy the user can replace, or ship your application in a form the user can relink against a modified library. Static linking is allowed, but then you owe the object files. LGPLv2.1, from February 1999, has the same structure in its Section 6. In every case, if you distribute the LGPL library itself, you also owe its source.
FFmpeg shows how thin the line between LGPL and GPL can be. The FFmpeg legal page says the project is licensed under the LGPL version 2.1 or later, with optional parts under the GPL. "If those parts get used the GPL applies to all of FFmpeg." The build system computes the resulting license from configure flags:
enabled version3 && { enabled gpl && enable gplv3 || enable lgplv3; }
if enabled nonfree; then
license="nonfree and unredistributable"
elif enabled gplv3; then
license="GPL version 3 or later"
elif enabled lgplv3; then
license="LGPL version 3 or later"
elif enabled gpl; then
license="GPL version 2 or later"
else
license="LGPL version 2.1 or later"
fiAdd --enable-gpl and every FFmpeg library in the build becomes GPL version 2 or later. Add --enable-version3 as well and it becomes GPL version 3 or later. The same source tree produces an LGPL binary or a GPL binary depending on one flag, and the license string compiled into the binary is the record of which.
Socket's license policy follows the same split: LGPL sits in the Weak Copyleft tier and GPL-2.0 and GPL-3.0 in the Strong Copyleft tier, and a team can Block, Warn, or Monitor each tier at the pull request that introduces a package.
How GPL binaries hide in npm packages
#FFmpeg is one of the most common ways GPL code enters a JavaScript project unannounced, because the license on the npm package that delivers it is often not the license of the binary inside. We inspected three widely used npm packages that deliver FFmpeg binaries. We did not run the binaries. Each one embeds its build configuration as plain strings, and strings reads them.
$ npm view ffprobe-static@3.1.0 license
MIT
$ npm pack ffprobe-static@3.1.0 --silent
ffprobe-static-3.1.0.tgz
$ tar -xzOf ffprobe-static-3.1.0.tgz package/bin/linux/x64/ffprobe \
| strings | grep 'license: ' | sort -u
libavcodec license: GPL version 3 or later
libavdevice license: GPL version 3 or later
libavfilter license: GPL version 3 or later
libavformat license: GPL version 3 or later
libavutil license: GPL version 3 or later
libpostproc license: GPL version 3 or later
libswresample license: GPL version 3 or later
libswscale license: GPL version 3 or later
$ tar -xzOf ffprobe-static-3.1.0.tgz package/bin/linux/x64/ffprobe \
| strings | grep -m1 -o -- '--enable-gpl --enable-version3'
--enable-gpl --enable-version3The figure and the table below carry the same data. All three packages deliver FFmpeg builds configured with --enable-gpl --enable-version3, so every binary we checked reports "GPL version 3 or later" for all eight FFmpeg libraries. Only ffmpeg-static declares that license in its metadata.
| Package | Declared license | Where the binary comes from | String compiled into the binary | Downloads, Oct 19 to 25, 2026 |
|---|---|---|---|---|
| ffmpeg-static 5.3.0 | GPL-3.0-or-later | Downloaded by an install script from GitHub releases | GPL version 3 or later | 1,772,006 |
| @ffmpeg-installer/ffmpeg 1.1.0 | LGPL-2.1 (platform packages: "GPLv3", LGPL-2.1, or a URL) | Optional platform dependency, such as @ffmpeg-installer/linux-x64 4.1.0 | GPL version 3 or later | 768,415 |
| ffprobe-static 3.1.0 | MIT | Six binaries inside the package tarball | GPL version 3 or later | 439,619 |
ffmpeg-static is the honest one, but its binary never appears in the registry tarball. The published package is seven files and 48,195 bytes. Its install script downloads a gzipped binary from the project's GitHub releases and writes a 79,826,272-byte statically linked executable into node_modules. The binary's own README says: "This static build is licensed under the GNU General Public License version 3." Since npm v12 made install scripts opt-in, that download does not happen unless someone approves the script, which makes the approval the moment GPL code enters the project. It is the same install script mechanism that almost every npm worm and credential stealer since late 2025 used to run its payload.
@ffmpeg-installer/ffmpeg declares LGPL-2.1 and contains no binary. The binary arrives as a transitive dependency: one of eight platform packages in its optionalDependencies, which npm installs for the matching OS and CPU. Six of the eight declare the non-SPDX string "GPLv3," one declares LGPL-2.1, and one declares a URL. The two platform tarballs we unpacked each hold a package.json, a short README, and the binary, with no copy of the GPL and no pointer to source. The darwin-x64 binary, declared LGPL-2.1, reports GPL version 3 or later like the rest.
ffprobe-static declares MIT and ships an MIT LICENSE file copyrighted to the wrapper's author. Its tarball holds six prebuilt ffprobe binaries totaling 351,499,535 bytes unpacked, and all six report GPL version 3 or later. The MIT license covers the JavaScript wrapper. Nothing in the package says the binaries carry different terms.
What this means depends on where the binary goes. A Node.js service that spawns ffmpeg on your own servers conveys nothing, so no GPL duty arises. An Electron app, a desktop installer, or a container image you ship to customers conveys the binary. You then owe the GPLv3 text and the Corresponding Source for that exact third-party build, including the 30 external libraries, such as libx264 and libx265, that its README lists as statically linked in. Your own JavaScript, which only passes command-line arguments to a separate executable, sits on the aggregate side of the FSF's line.
License detection that relies on declared metadata and license files reports MIT for ffprobe-static. The evidence of the GPL is a string compiled into a binary. When detection and reality disagree, Socket's license overlays let a team replace the detected license for a package and version range, so that policy checks and generated attribution files reflect the real terms. If the file an overlay targets changes in a later version, the overlay stops applying and the default detection result returns.
How the GPL is enforced
#The GPL is enforced through copyright: a licensee who breaks its conditions loses the license and is left distributing someone else's code without permission. GPLv2 Section 4 makes termination automatic and permanent: any noncompliant distribution "is void, and will automatically terminate your rights under this License." GPLv3 Section 8 softens that. A first-time violator who receives notice gets the license back permanently by curing the violation within 30 days. A violator who stops on their own is reinstated permanently if the copyright holder does not notify them within 60 days.
Many GPL disputes end without a lawsuit. A typical one is the Tencent zipalign.py incident in 2024: a Tencent project ported a GPLv3-or-later utility, replaced its license with BSD-3-Clause, and swapped out its copyright notice. After the author's public complaint and a DMCA takedown request, Tencent removed the file from its main branch and said it was preparing to remove the git history and PyPI packages that contained it. Relicensing someone else's GPL code without permission does not work. The author also pointed out that downstream users who redistributed the file could be in violation themselves.
That is the open problem with the GPL license in a modern dependency tree. Its reach depends on three facts that no package manifest records: how a component is linked, how it was built, and whether it leaves your machine. FFmpeg's configure script computes a binary's license from its build flags. A registry stores a string a maintainer typed at publish time. Until package formats carry per-artifact license data, the license string is a claim and the binary is the evidence, and license compliance has to read the evidence.
