On 27 October 2026 CISA added CVE-2026-111497 to its catalogue of known exploited vulnerabilities, under the rather dry title "Unchecked Return Value" for a decoder that writes where it should not. Brotli is the compression most web servers use when they answer with Content-Encoding: br, and the decoder is a small C library that turns those bytes back into a page. Google had published fixed versions on 21 October.
On a FreeBSD server the morning after that announcement runs to four commands:
pkg audit -F
pkg shlib -R libbrotlidec.so.1
pkg upgrade
service -R
The first fetches the vulnerability database that the port committers and the security team maintain, and checks the installed packages against it; FreeBSD's entry for Brotli went in on 22 October and marks every version below 1.2.1 as affected. The second lists, according to its manual page, the installed packages "that require library by containing binaries that link to it". The third replaces the library, and pkg-upgrade(8) describes what happens next without any help from the administrator: "Where a package on the work list supplies a shared library, and that library has been updated, all packages requiring that shared library will also be added to the work list as reinstallation jobs." The fourth restarts every enabled local service, so that nothing keeps the old library in memory. After that, every program on the machine that decodes Brotli does so with the repaired code, because there was only ever one copy of it.
The rule behind the four commands
None of this depends on luck or on a diligent maintainer. It is written into the Porter's Handbook, the rulebook every FreeBSD port is built to, under a heading that leaves little room for doubt: "Why Bundled Libraries Are Bad". The first reason it gives is the one that mattered this week: "If vulnerabilities are found in the upstream library and fixed there, they might not be fixed in the library bundled with the port." The instruction that follows is short: "Whenever possible, use the unbundled version of the library by adding a LIB_DEPENDS to the port." Bundling is allowed only where upstream "has a good track record on security" and unbundling would mean overly complex patches, and the special cases need the ports management team's consent.
Node.js shows how far that rule reaches. Node bundles its dependencies by default, Brotli among them, and the FreeBSD port turns that off. The Makefile of www/node24 passes --shared-brotli to Node's configure script, along with a dozen other --shared- switches, and declares libbrotlidec.so:archivers/brotli as a library dependency. The shared build is simply how the port is made, with no option to bring the bundled copy back.
Every package then records what it links. The catalogue of each FreeBSD package repository carries, for every package, the shared libraries it requires, and pkg reads that list when it decides what to reinstall. The ports themselves are built in one run, every package against the same libraries, so the library a program finds at run time is the one it was compiled against. The result is a single place to fix, and a package manager that knows who depends on it.
This week, counted
I read the catalogue of the official repository for FreeBSD 15 on amd64 this morning, packagesite.yaml in latest. Sixty-four packages require Brotli's shared library, among them node24, curl, apache24 and freetype2. All of them load libbrotlidec.so.1 from the one package archivers/brotli, and the ports tree took that package to 1.2.1 on 23 October. By the time the exploited list named the flaw, the fix had been waiting for four days. The repository serves 1.2.1 today.
The calendar of the week, in order:
21 October Google publishes fixed Brotli releases
22 October FreeBSD's vulnerability database lists brotli below 1.2.1
23 October archivers/brotli moves to 1.2.1 in the ports tree
25 October www/node24 takes the October Node.js security release
27 October CISA adds CVE-2026-111497 to its exploited list
28 October the repository serves brotli 1.2.1; 64 packages use it
Sources: Google's release page, FreeBSD VuXML, the ports commits for both ports, the CISA catalogue and packagesite.yaml in FreeBSD:15:amd64/latest, read on 28 October 2026.
The detail that makes the case better than any argument sits in the same repository. The node24 package still stands at 24.21.0 this morning. The October Node.js release fixed nine other flaws in Node's own code, the port took it on 25 October, and the package build has not caught up yet, so FreeBSD's own vulnerability database lists that package as affected. Yet the Brotli flaw inside that very package has been closed since the library moved to 1.2.1, days before the new Node arrived, because the decoder was never inside the binary. So the library was repaired on its own schedule, and every program using it was repaired along with it.
The bundled way, for comparison
The other approach has a respectable reason, and Node.js states it in its build documentation: "By default Node.js is built so that all dependencies are bundled into the Node.js binary itself. This provides a single binary that includes the correct versions of all dependencies on which it depends." The tarball from nodejs.org runs the same on any Linux, and the official Docker image downloads that tarball and unpacks it. For whoever ships the software, a single artefact with a single support matrix is close to ideal, and on the first day the installation is a doddle.
On the day of the flaw the inventory begins. Node's advisory says the vulnerable decoder was "bundled with Node.js", and a detailed test of other software concluded that "Software that carries its own copy of the Brotli decoder stays vulnerable until it ships its own update." Its list runs to a fair few names, the Python packages brotli and brotlicffi, Bun, Envoy and Git for Windows among them, each waiting for a release of its own. Tanium, whose business is finding such things, summed up the fiddly part: "The hard part is finding every copy of Brotli you own, because it rarely shows up as an application in its own right."
Debian deserves its due here, because it follows the same principle as FreeBSD. Its policy says that binary packages should "reference the libraries already in Debian", its Node.js depends on the system's libbrotli1, and its security team fixed that library for Debian 13 in DSA-6582-1. The difference lies in the version. The Node.js that Debian 13 ships is 20.19.2, and the Node.js project ended support for the 20 line on 30 April 2026, so a team that wants a supported Node on Debian ends up with the binary from nodejs.org and a private copy of Brotli inside it. FreeBSD offers node24 and node22 from the same shared build as everything else.
The limit
What other package managers install stays theirs. Python wheels from pip and Electron applications carry their own copies on FreeBSD as well; the shared build covers what comes through pkg, and the rest is the responsibility of the package manager that delivered it.
Packages follow the ports tree by a few days. The node24 security update has been in the ports tree since 25 October and is not yet in the latest repository. Whoever builds with Poudriere has it the same evening, and the shared Brotli covered the decoder in the meantime.
A jail keeps its own package set. Ten jails mean ten runs of pkg upgrade, each from the same repository; pkg -j runs them from the host.
The rule has exceptions by design. Emulators such as Wine bundle libraries of another architecture, and the Porter's Handbook asks the ports management team to approve every such case.
Other systems spent the week counting copies of Brotli. A FreeBSD server counted one, and
pkg upgradehad already found the other sixty-three.