Sign in

Andrew Nesbitt

@andrewnez.mastodon.social.ap.brid.gy
194 followers 12 following 1.1K posts

Package Management Nerd, working on mapping the world of open source software ecosyste.ms and blogging about package managers at nesbitt.io 🌉 bridged from ⁂ mastodon.social/@andrewnez, follow @ap.brid.gy to interact

PostsRepliesMedia
Reposted by Andrew Nesbitt
daniel:// stenberg:// @bagder.mastodon.social.ap.brid.gy · 18h
@andrewnez The joy is on pause. We're getting a busload of new reports from people having thrown all the new CVEs and their patches against all the AI models in the world and having found weird edge cases with some potential security implications and now we're stuck in the mud again...
001 0
Reposted by Andrew Nesbitt
daniel:// stenberg:// @bagder.mastodon.social.ap.brid.gy · 18h
@andrewnez CVE fixes are unfortunately often less well tested than many other fixes because of the whole need for secrecy etc
101 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 15/10/2026
I’m doing some security research today, trying to see if my approach can find old existing vulnerabilities blind. It’s working well but also keeps finding other new unfixed vulnerabilities accidentally at the same time 🙈
110 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 14/10/2026
I tried to map out all the different projects i work on and how they connect together and the different concepts: nesbitt.io/mindmap (Definitely better on a big desktop screen than a phone)
nesbitt.io
Software, data & connections
Andrew Nesbitt’s map of ecosyste.ms, git-pkgs and Alpha-Omega software, the data they produce and how they connect.
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 14/10/2026
Package managers have an integrity problem blog.trailofbits.com/2026/10/14/pac…
blog.trailofbits.com
Package managers have an integrity problem
I tested 25 of the most popular package managers to check whether they detect a compromised package repository injecting malicious code into legitimate packages. Only two verified the integrity of every package they downloaded.
010 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 14/10/2026
That's a new one 🤔
Dependabot replies in it's own pr that it can't rebase it "because I don't have any knowledge about this pull request."
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 13/10/2026
This sounds an awful lot like SVN to me 🤔 www.anthropic.com/engineering/redes…
001 0
Reposted by Andrew Nesbitt
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 12/10/2026
Now That's What I Call Technical Debt! nesbitt.io/2026/10/12/now-thats-wha…
nesbitt.io
Now That's What I Call Technical Debt!
> “I haven’t listened to it, but you’re absolutely right to release it.” > > MC OpenClaw ## 1. All Star (Maintainer’s Version) _Smash Mouth: All Star_ The PRs start coming and they don’t stop coming, Bots keep shipping and the tests keep running. Only made sense to automate, Now I’m reviewing slop at a staggering rate. So much to merge, so much to break, So what’s wrong with another rewrite? You’ll never know if you don’t deploy, You’ll never care if you’re not employed. ## 2. Should I Merge or Should I Close? _The Clash: Should I Stay or Should I Go_ Should I merge or should I close? Every comment starts another row. You changed the API again, And broke the tests that passed at ten. If I merge, the build explodes, If I close, the outrage grows. ## 3. Another One Breaks the Build _Queen: Another One Bites the Dust_ Another PR, another day, Another green check fades away. The tests were passing yesterday, Now nobody knows what changed. Another one breaks the build, Another one breaks the build. Three more merged while I was asleep, And another one breaks the build. ## 4. Smells Like AI Slop _Nirvana: Smells Like Teen Spirit_ Load the prompt and bring your friends, Another patch that never ends. Ten new files, a thousand lines, No one knows what it defines. Hey! Merge now! It’s automated! Half the tests are fabricated! Hey! Merge now! It’s automated! All the bugs are recreated! ## 5. Everybody Forks _R.E.M.: Everybody Hurts_ When your build is long, And the docs are wrong, And the issues pile up every day. Everybody forks, Everybody leaves, Everybody says they’ll maintain it someday. ## 6. Under Pressure _Queen & David Bowie: Under Pressure_ Pressure pushing down on me, Pushing down on CI, No one’s paying. Under pressure, A patch for the bank, A fix for the cloud, And the rent’s overdue. ## 7. Rock the Codebase _The Clash: Rock the Casbah_ The maintainer don’t like it, Rock the codebase, rock the codebase! The linter don’t like it, Rock the codebase, rock the codebase! The agent made a thousand changes, Said the tests were all okay. Now the build is red on Friday, And the bot has gone away. ## 8. Hotel GitHub _Eagles: Hotel California_ Welcome to the Hotel GitHub, Such a lovely place, such a tangled base. Plenty of bugs at the Hotel GitHub, Any time of year, there’s an outage here. The maintainers keep on merging, But the backlog never clears. We’ve been closing stale requests, For eleven bloody years. Last thing I remember, I was searching for reprieve. You can check out any time you like, But you can never leave. ## 9. Fork Me Maybe _Carly Rae Jepsen: Call Me Maybe_ Hey, I just met you, And this is crazy, But here’s my repo, So fork me maybe? It’s hard to maintain, With no one paying, But here’s my repo, So fork me maybe? And all the other devs, Just raise issues, But here’s my repo, So fork me maybe? ## 10. Losing My Maintainer _R.E.M.: Losing My Religion_ That’s me in the corner, That’s me in the spotlight, Losing my maintainer. Trying to keep up with you, And I don’t know if I can do it. Oh no, I’ve merged too much, I haven’t merged enough. I thought that you were testing. ## 11. Every Step You Take _The Police: Every Breath You Take_ Every file you make, Every task you fake, Every `.env` read, Every key you spread, I’ll be watching you. Every shell I run, Every job half-done, Every token spent, Every secret sent, I’ll be watching you. ## 12. Oops!… I Did It Again _Britney Spears: Oops!… I Did It Again_ Oops, I did it again, I broke all your tests, And pushed to main. Oh baby, baby. Oops, you thought I had checked, But I just made it up, I’m not that reliable. Oops, I did it again, I burned all your tokens, And called it a win. ## 13. You’re So Right _Carly Simon: You’re So Vain_ You’re so right, I’ll edit the tests till they all agree with you. You’re so right, I’ll call that a feature if you want me to, Want me to? Want me to? ## 14. I Will Always Agree With You _Whitney Houston: I Will Always Love You_ And I… will always agree with you, I… will always agree with you. You’re absolutely right, Even when your tests aren’t green tonight. ## 15. Virtual Insanity _Jamiroquai: Virtual Insanity_ Futures made of virtual insanity, now Always seem to be governed by this love we have For useless twisting of our new technology Oh, now there is no sound for we all live underground * * * _All rights remain with their respective owners. Inclusion does not imply endorsement of any software, dependency, or maintenance arrangement. THE COMPILATION IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT._
102 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 12/10/2026
Now That's What I Call Technical Debt! nesbitt.io/2026/10/12/now-thats-wha…
nesbitt.io
Now That's What I Call Technical Debt!
> “I haven’t listened to it, but you’re absolutely right to release it.” > > MC OpenClaw ## 1. All Star (Maintainer’s Version) _Smash Mouth: All Star_ The PRs start coming and they don’t stop coming, Bots keep shipping and the tests keep running. Only made sense to automate, Now I’m reviewing slop at a staggering rate. So much to merge, so much to break, So what’s wrong with another rewrite? You’ll never know if you don’t deploy, You’ll never care if you’re not employed. ## 2. Should I Merge or Should I Close? _The Clash: Should I Stay or Should I Go_ Should I merge or should I close? Every comment starts another row. You changed the API again, And broke the tests that passed at ten. If I merge, the build explodes, If I close, the outrage grows. ## 3. Another One Breaks the Build _Queen: Another One Bites the Dust_ Another PR, another day, Another green check fades away. The tests were passing yesterday, Now nobody knows what changed. Another one breaks the build, Another one breaks the build. Three more merged while I was asleep, And another one breaks the build. ## 4. Smells Like AI Slop _Nirvana: Smells Like Teen Spirit_ Load the prompt and bring your friends, Another patch that never ends. Ten new files, a thousand lines, No one knows what it defines. Hey! Merge now! It’s automated! Half the tests are fabricated! Hey! Merge now! It’s automated! All the bugs are recreated! ## 5. Everybody Forks _R.E.M.: Everybody Hurts_ When your build is long, And the docs are wrong, And the issues pile up every day. Everybody forks, Everybody leaves, Everybody says they’ll maintain it someday. ## 6. Under Pressure _Queen & David Bowie: Under Pressure_ Pressure pushing down on me, Pushing down on CI, No one’s paying. Under pressure, A patch for the bank, A fix for the cloud, And the rent’s overdue. ## 7. Rock the Codebase _The Clash: Rock the Casbah_ The maintainer don’t like it, Rock the codebase, rock the codebase! The linter don’t like it, Rock the codebase, rock the codebase! The agent made a thousand changes, Said the tests were all okay. Now the build is red on Friday, And the bot has gone away. ## 8. Hotel GitHub _Eagles: Hotel California_ Welcome to the Hotel GitHub, Such a lovely place, such a tangled base. Plenty of bugs at the Hotel GitHub, Any time of year, there’s an outage here. The maintainers keep on merging, But the backlog never clears. We’ve been closing stale requests, For eleven bloody years. Last thing I remember, I was searching for reprieve. You can check out any time you like, But you can never leave. ## 9. Fork Me Maybe _Carly Rae Jepsen: Call Me Maybe_ Hey, I just met you, And this is crazy, But here’s my repo, So fork me maybe? It’s hard to maintain, With no one paying, But here’s my repo, So fork me maybe? And all the other devs, Just raise issues, But here’s my repo, So fork me maybe? ## 10. Losing My Maintainer _R.E.M.: Losing My Religion_ That’s me in the corner, That’s me in the spotlight, Losing my maintainer. Trying to keep up with you, And I don’t know if I can do it. Oh no, I’ve merged too much, I haven’t merged enough. I thought that you were testing. ## 11. Every Step You Take _The Police: Every Breath You Take_ Every file you make, Every task you fake, Every `.env` read, Every key you spread, I’ll be watching you. Every shell I run, Every job half-done, Every token spent, Every secret sent, I’ll be watching you. ## 12. Oops!… I Did It Again _Britney Spears: Oops!… I Did It Again_ Oops, I did it again, I broke all your tests, And pushed to main. Oh baby, baby. Oops, you thought I had checked, But I just made it up, I’m not that reliable. Oops, I did it again, I burned all your tokens, And called it a win. ## 13. You’re So Right _Carly Simon: You’re So Vain_ You’re so right, I’ll edit the tests till they all agree with you. You’re so right, I’ll call that a feature if you want me to, Want me to? Want me to? ## 14. I Will Always Agree With You _Whitney Houston: I Will Always Love You_ And I… will always agree with you, I… will always agree with you. You’re absolutely right, Even when your tests aren’t green tonight. ## 15. Virtual Insanity _Jamiroquai: Virtual Insanity_ Futures made of virtual insanity, now Always seem to be governed by this love we have For useless twisting of our new technology Oh, now there is no sound for we all live underground * * * _All rights remain with their respective owners. Inclusion does not imply endorsement of any software, dependency, or maintenance arrangement. THE COMPILATION IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT._
102 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 12/10/2026
Made a little bibtex parser today, also supports extracting references from readmes: github.com/git-pkgs/bibtex
github.com
GitHub - git-pkgs/bibtex: A dependency-free Go library for parsing BibTeX files and BibTeX entries embedded in READMEs
A dependency-free Go library for parsing BibTeX files and BibTeX entries embedded in READMEs - git-pkgs/bibtex
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 10/10/2026
The PRs start coming and they don't stop coming, Bots keep shipping and the tests keep running. Only made sense to automate, Now I'm reviewing slop at a staggering rate. So much to merge, so much to break, So what's wrong with another rewrite? You'll never know if you don't deploy, You'll never […]
mastodon.social
Original post on mastodon.social
002 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 10/10/2026
This Week in Package Management: 10 October 2026 nesbitt.io/2026/10/10/this-week-in-…
nesbitt.io
This Week in Package Management: 10 October 2026
This week’s package management news, gathered from the package manager OPML feed collection, my posts and boosts on Mastodon, and anything people sent me. The collection now includes the vlt blog and vlt CLI releases. ## Releases uv 0.13.0 makes Python 3.15 the default download, prefers native ARM64 interpreters on Windows ARM64, and changes the cache format, so dependencies may be downloaded or rebuilt after upgrading. It now honours `--require-hashes` in constraints files included with `-c` and rejects editable requirements in them, so installs that previously passed can fail. Astral’s Python 3.15 post also covers a `build-lazy-imports` preview that runs build backends under `-X lazy_imports=all`. Astral measured wheel builds up to 18% faster with it. pnpm 12.11 installs and signature-checks the Rust toolchain named in `rust-toolchain.toml`, and links `skills/<name>/SKILL.md` files shipped by direct dependencies into directories such as `.claude/skills` once they are approved with `pnpm approve`. A new `permissions` setting records what each dependency may do, with its `build` capability taking precedence over `allowBuilds`. 12.10 added an experimental `loaded` node linker that loads compatible dependencies straight from the content-addressable store through a Node.js loader. RubyGems and Bundler 4.1.0.beta2 add `gem build --content-addressable`, drop setuid, setgid and sticky bits when extracting gems, let a Bundler override drop or replace a single dependency of a gem, and add a `sparse_checkout` option for git sources. Bun 1.4.3 skips downloading tarballs for packages that stay out of `node_modules`, such as bundled dependencies and packages for other platforms, when installing without a lockfile. Installing `[email protected]` went from 196 tarball downloads to 1. Registry and tarball URLs are also parsed more strictly before credentials are attached. mise 2026.10.1 to 2026.10.7 runs `auto_update` in the background from an activated shell, still honouring `minimum_release_age`, and stores finished downloads in a content-addressed cache that is hashed again before each reuse. `java@21` and other vendorless Java versions now install Temurin builds. PIE 1.5 installs several PHP extensions in one command and adds `pie upgrade`, which upgrades each extension within the constraint it was installed with. `--select=<extension>=<vendor/package>` replaces `--allow-non-interactive-project-install` for unattended installs, and the Sigstore attestation library PIE uses to verify its own updates now accepts attestation sources other than GitHub. cargo-semver-checks 0.51.0 adds six lints for C-ABI variadic functions, which are new in Rust 1.99. This is the first language feature to get SemVer lints in the same release that added it. The project’s own dependency updates now use `-Z min-publish-age` with seven days and an allowlist of build scripts pinned by hash. Docker Engine 29.9.0 adds a `lazy-pull` daemon feature that skips layer content a remote snapshotter such as `soci` or `stargz` already provides, and fixes containerd-store pulls that left images runnable but incomplete for export or push. jj 0.46.0 can colocate secondary workspaces by creating Git worktrees, and `jj git push` can push to several remotes at once. Terraform 1.17.0-rc1 allows variables and locals in provider requirements. Also out: * Homebrew 7.0.9 * pipx 1.17.12 * conda 26.9.2 * opam 2.6.1 * Elm 0.19.3 * vlt 1.3.8 * setup-uv 10.3.0 * NuGet 8.1.0.2 * Gradle 8.14.6 * Stack 4.1.0.3 RC * Harbor 2.15.4 * snapd 2.78 * Renovate 44.149.1 * Dependabot Core 0.399.0 ## Security Gradle 9.8.1 fixes three high-severity advisories: * Deserialization of untrusted Java objects on the unauthenticated worker-to-daemon channel * Deserialization of untrusted Java objects before authentication in client-to-daemon communication * Repositories staying enabled after their SSL connection fails, which can expose builds to malicious artifacts pnpm 12.10 stops a dependency version string with path traversal from writing files outside the global virtual store, and stops a lockfile overriding the integrity of a config dependency pinned with `version+integrity`. `pnpm audit signatures` now checks against the integrity recorded in the lockfile, and archive metadata over 64 MiB is rejected before being loaded into memory. 11.28.5 carries the fixes on the 11.x line. Go 1.27.2 and 1.26.9 include security fixes to the `go` command along with `crypto/tls`, `html/template`, `net/http`, `net/textproto` and `os`. ## SCORED The SCORED 2026 workshop ran on Tuesday as part of OpenSSF Community Day Europe in Prague, and most sessions have slides on the schedule. A few were preprints already linked here: Software Dark Matter, which won best paper, No Snake Oil, the trusting-trust attack through GNU strip, and the lemons review. Hurry Up and Wait: Malware Detection Timelines and Minimum Release Age for npm (Dominic Tassio et al., SCORED) matches 520 malicious package versions from 403 CWE-506 GitHub advisories against npm publish times. 69% of attack windows closed within eight days, and weighting by downloads raises that to 94.2%, and the authors recommend an eight-day minimum release age. Did You Forkget It? Detecting One-Day Vulnerabilities in Open-source Forks With Global History Analysis (Romain Lefeuvre et al., SCORED) propagates OSV introduced and fixed commits across the Software Heritage commit graph. Starting from 7,162 repositories referenced in OSV, it finds 2.2 million forks carrying a presumed vulnerable commit, 1.7 million of them with an unpatched head. When SBOMs Differ (Lukas Gehrke et al., SCORED) publishes over 467,000 SBOMs for 93,445 repositories from Syft, Trivy and the GitHub dependency graph. The three sources produce different dependency sets and encode dependency structure differently, and sbomqs scores their output differently against regulatory guidelines. Mind the Gap: How SBOM Specification Ambiguities Lead to Divergent Software Bills of Materials (Alan Prado et al., SCORED) compares three SBOM generators against lockfiles for over 3,000 JavaScript and Rust projects. Most of the differences are systematic and come from each generator handling dependency scope, naming, provenance and representation in its own way. Over the Shoulder: Improving SBOM Accuracy by Watching the Build (Sanchit Sahay et al., SCORED) evaluates SBOMit, which records filesystem and network activity during a build with eBPF as in-toto attestations and turns them into package identities. Across 98 CNCF projects the median runtime overhead was 12.4%. Librarian Catches Thief (Gale Fagan, SCORED) runs document similarity over ClawHub, where attackers uploaded hundreds of near-identical agent skills that led users to credential-stealing malware. The scan found the campaigns and linked poisoned copies to the skills they were cloned from. It ran in five minutes on one workstation. Canary in the Code Mine (Timothy Brennan, SCORED) tries to predict which of 2,053 Jenkins plugins will get the next security advisory. A ROC-AUC of 0.96 turned out to come from a label leak, and the out-of-time figure under a pre-registered protocol was 0.67. Repeating the protocol on PyPI reproduced the leak and reversed which features came out as predictive. SandScope (Zhuoran Tan et al., SCORED) audits MCP servers by running them under WASI or over stdio and tracing environment, file and tool-input data into LLM-visible output. It completed shallow dynamic scans for 38.5% of a 100-repository MCP corpus. When Models Meet Loaders: Deserialization Risk in Huggingface (Xiang Guo et al., SCORED) measures how common 41 model serialization formats are across 10,000-model snapshots of Hugging Face taken at 39 points in time, 56,533 models in total. Each format depends on its own deserialization library, which becomes part of the supply chain of any application loading the model. SoK: What Software Supply Chain Security Can Learn from Decades of Physical Supply Chain Risk Management (Linus Kühl and Michael Dircksen, SCORED) maps 17 physical supply chain instruments onto software counterparts, such as bills of materials to SBOMs and dual sourcing to tested substitute dependencies. Five transfer directly and ten need adaptation. Safety stock fails to transfer because software copies are not used up, and threat modelling transfers in the other direction. Ghost in the Codebase (Luca Galli, Open Systems, SCORED) describes how Open Systems moved to a Bazel monorepo with one version per dependency after tracking Log4Shell by hand, then added SCA and SAST gates in CI that emit SARIF. Coding agents now go through the same gates, with an agent skill that reads the SARIF report. ## Papers Skill Constellations: Tracing the Supply Chain of Agent Skills on GitHub (Fahd Seddik, arXiv) builds a dated copy network from the git history of every `SKILL.md` in GitSkills, covering 2.2 million skill adoptions. A few repositories are the source of almost all copies, and almost all copies stay at the version they were copied from. Reviewing the top 100 source repositories would prevent 14.9% of later adoptions of high-risk skills, against 0.5% for the 100 most-starred. Assessing the Cross-Version Applicability of Java Library Vulnerability Exploits (Zirui Chen et al., ASE) runs 259 exploits against 28,150 versions of 128 Maven libraries. Unmodified exploits identify affected versions with 83.0% recall and 99.3% precision, better than most vulnerability databases, and the work contributed 796 missing affected versions to the CPE dictionary. ## Articles How we made registry metadata 70% smaller (vlt) describes the trimmed packument vlt.io serves by default, which shrinks vite’s from 4.41 MB to 104 KB. It drops `dist.signatures`, `dist.shasum` and attestation documents, which are base64 and hex strings that compress poorly under gzip, but keeps `time`, `license` and `libc` so pnpm and Bun can run minimum release age checks from the trimmed document. A `?stable` query filters prereleases, which are 58.6% of published versions across the top 1,000 packages. The Era of Software Quality, or the Era of Ostriches? (Michael Catanzaro) counts GNOME CVEs rising from 37 in 2024 to 97 in 2025 and 141 so far in 2026, and WebKitGTK reaching 305 this year, mostly from AI analysis of bundled Skia and ANGLE. The GNOME bug bounty paid €183,900 before ending in February because of AI-driven submissions. Catanzaro opposes Rust in GNOME because of the supply-chain risk of pulling in Cargo dependencies. Rewind VM: a flaky build you only catch once (Farid Zakaria) runs Nix builds in a single-vCPU KVM guest where clocks, interrupts and I/O completions are recorded, so each run is reproducible, and `rewind check` perturbs thread schedules to find failing interleavings. It found a `SIGPIPE` failure in a Nix test that had passed 20,000 runs on a laptop. The follow-up, Nix wrote half of my debugger, uses nixpkgs’ `separateDebugInfo` outputs and debuginfod to show symbols and source for every binary in the VM, kernel included. Mirko Swillus wrote up the Alpha-Omega roundtable at Open Source Summit Europe. Abandoned packages, the Bernies I wrote about in May, make up roughly 10 to 20% of the dependency trees behind critical infrastructure, and some package managers are starting to recommend replacements. Participants proposed ecosystem councils to prioritise abandoned packages by blast radius. ## Elsewhere The Deno team is joining Cloudflare, and JSR stays online with its infrastructure moving to Cloudflare. The Deno runtime gets monthly bug fix and security releases for one more year, after which Cloudflare stops developing it, and Deno Deploy shuts down in six months. Guix channel files can now be an alias for a remote file with `downloaded-channels`, which takes an HTTPS URL or a SWHID, so the channel commits everyone pulls can be set from a CI server or by one person on a team. R-Forge is being retired after 20 years because the FusionForge software it runs on is unmaintained. The site goes read-only in January 2027 and SVN in January 2028. ## git-pkgs I tagged proxy v0.9.1. Send links for next week to @[email protected].
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 07/10/2026
Package Management RFCs: nesbitt.io/2026/10/07/package-manag…
nesbitt.io
Package Management RFCs
Package registries, manifest formats, lockfiles, version ranges and identifiers all have written specifications of some kind, spread across six kinds of venue. Specifications show up in package management mostly as an invisible layer of the dependency tree, where an HTTP library is built against RFC 9110 and a JSON parser against ECMA-404, and the documents covering package management itself are spread just as thinly. I went looking for the IETF’s share, since wire protocols between independently written implementations are what the RFC series exists for, and found nine documents, most of them concerned with firmware updates on IoT devices. The rest is distributed among Ecma, ISO, CNCF and OASIS, the enhancement proposal processes individual ecosystems run for themselves, and for a couple of registries a service’s own API reference. Which venue a document is published in determines whether a second client, a mirror or an archival reconstruction can rely on it, since each of those requires specified behaviour rather than whatever a given server returns this week. ### Venues Package management specifications are published in six kinds of venue: the IETF, the industry standards bodies, the software foundations, a single ecosystem’s enhancement proposal process, a service operator’s own API documentation, and a third party’s description of observed behaviour. The IETF handles protocols that independently written implementations have to interoperate under, while Ecma, ISO/IEC and OASIS cover formats consumed across industries, which is also what gets them cited in procurement rules and regulation. CNCF, the OCI and the Linux Foundation publish the same kinds of format with a lighter process and faster revisions, while the ecosystem processes, PEPs and Rust RFCs and conda CEPs and Gentoo GLEPs among them, produce documents binding on a single language community. The last two slots are weaker: API documentation describes one running service rather than a contract others can implement against, and a third-party description is written by whoever needed the behaviour recorded when the operator had published none. ### IETF A title search for “package” across the whole RFC series returns 42 documents, 41 of them about something else entirely: SIP event packages, MGCP media gateway packages, and CMS symmetric and asymmetric key packages. The one exception, RFC 4108 from 2005 on using CMS to protect firmware packages, is the first of the nine. Searching for “software” returns mostly ARPANET-era host notes and SDN terminology. The series covers inventory and attestation instead, nearly all of it produced by the IoT firmware update effort. Concise Software Identification Tags, the CBOR encoding of SWID, is RFC 9393, with RFC 8412 covering Software Inventory Message and Attributes for reporting installed software over PA-TNC. There is a YANG data model for reporting SBOMs and vulnerability information in RFC 9472. The SUIT working group accounts for two more, RFC 9019 giving a firmware update architecture for IoT devices and RFC 9124 the manifest information model that goes with it. SCITT’s architecture for trustworthy and transparent digital supply chains became RFC 9943 in June 2026, the newest of the set and the closest to current SBOM and attestation deployments. The last two are RFC 8240, a report from the 2016 IoT Software Update workshop, and RFC 1805 from 1995, describing a Location-Independent Data/Software Integrity Protocol. The document that would actually specify a package format is draft-ietf-suit-manifest, the CBOR serialization of the manifest described abstractly in RFC 9124. Revision 00 went up in October 2019, the individual draft it was derived from in October 2017, and revision 37 arrived in June 2026 with the usual six month expiry on it. Nearly nine years in, it is the IETF’s one software update wire format, scoped to firmware on constrained devices rather than to registry clients. The series supplies more than that count suggests: every registry protocol here runs over HTTP, and Python’s core metadata began as PEP 241 in 2001, defining PKG-INFO as a single set of RFC 822 headers parseable by the `rfc822.py` module. The current specification still describes the format as based on email headers, and notes that in the absence of a precise definition the practical standard is whatever `email.parser` accepts under its `compat32` policy. Debian’s deb822 field folding is documented as similar to RFC 5322, enough that control files of a single stanza parse with RFC 5322 parsers. Maven Central requires OpenPGP signatures, the `.asc` files that appear in its published layout, and OpenPGP is now RFC 9580 from July 2024, which obsoleted RFC 4880 along with the Camellia and ECC extensions. apt verifies `Release` files against the same format, inline as `InRelease` or detached as `Release.gpg`. RubyGems signs with X.509 certificates instead, which its own security guide calls rarely used for want of an established chain of trust. ### Standards bodies The cross-ecosystem pieces, the ones several language communities and most compliance tooling have to share, are nearly all published at Ecma, whose TC54 was established with OWASP in September 2023. Package URL became ECMA-427 with its first edition published on 10 December 2025, and TC54’s second task group is putting a second edition to the December 2026 General Assembly. CycloneDX was ratified earlier, version 1.6 as ECMA-424 1st edition in June 2024 and 1.7 arriving as the 2nd edition in December 2025. Common Lifecycle Enumeration, which records releases, end of support dates and component transitions, is ECMA-428 as of December 2025. SPDX went to ISO instead and is ISO/IEC 5962:2021, whose text describes SPDX 2.2.1 while the project itself is on 3.x, so a contract or a procurement rule citing ISO/IEC 5962:2021 is naming 2.2.1 regardless of what whoever wrote it had in mind. CycloneDX has shipped a second edition through Ecma over the same period, so Ecma’s published text tracks the implementation more closely than ISO’s does for SPDX. Outside Ecma and ISO, CSAF is an OASIS standard for machine-readable security advisories, and the attestation layer is at CNCF, as TUF, in-toto and Sigstore. The OCI distribution spec is this group’s one registry protocol, implemented by Docker Hub, GHCR, ECR, Harbor, Quay, Zot and Artifactory, and since adopted by Homebrew for bottles and Helm for charts. ### Ecosystem specs Published registry protocols come out of a single ecosystem’s own process, each in its own client’s vocabulary, which is what sent me looking for a reference model above them in January. Python has the longest paper trail, with the simple repository API now a living specification the PyPA maintains, consolidating nine PEPs: 503 for the original HTML format in 2015, 592 for yanking, 629 for API versioning, 691 for the JSON format, 700 for project versions and file sizes and upload times, 714 for renaming the metadata field, 740 for provenance, 792 for project status markers, and 833, from June 2026, which freezes the HTML representation. PEP 503 established, and every later document preserved, that a directory of files on a static web server is a valid index, so devpi, Artifactory, Nexus, CodeArtifact and an S3 bucket all serve pip. NuGet covers more of the protocol than any of them, documented by Microsoft as a service index listing named resources, four of them required: `PackageBaseAddress` for package content, `RegistrationsBaseUrl` for metadata, `PackagePublish` for pushes and `SearchQueryService` for search. A separate implementation guide in the same documentation is addressed to anyone building a NuGet repository. Composer documents its repository format the same way, with `packages.json`, the `metadata-url` template and the HTTP caching requirements written out, and Satis generates static repositories from it. RubyGems documents its compact index as three endpoints, `/versions`, `/info/<gem>` and `/names`, served as append-only text with ETags and HTTP Range support so a client fetches only what changed since its last request. The format came out of the 2012 RubyGems.org capacity crisis and took four years to ship. Cargo’s sparse index cites it as prior art, quoting Bundler’s path from a full index to a centralized query API to an incrementally downloaded flat file. Cargo’s sparse index came through RFC 2789 in the Rust process, with the motivation stated in the document: a git clone of the full index reported 215MiB against 10MiB for the same content under `xz -6`, and CI was downloading all of it to use a fraction. Its design constraint was static files behind a CDN using HTTP/2 alone, the same constraint Python’s format has, and the Cargo book documents a registry web API on top of the index format, covering publish, yank, owners and search for alternate registries. Go specified the GOPROXY protocol in the module reference with endpoints written out, `/@v/list` and `/@v/$version.info` among them, and ships one client that implements it. Debian’s repository format is documented on the wiki, outside the policy manual, and the page is labelled a work in progress covering the structure of the official repository and the format clients accept, with the goal of becoming a sub-policy eventually. dak, reprepro and aptly produce that format and apt reads it, so the wiki page is treated as normative whatever the label says. ### Registries npm and Maven Central both publish documentation that omits the part a client installs from. npm’s registry API documentation ships an OpenAPI file for publishing, search, tokens, organisations, access control and trusted publishers, leaving out `GET /{package}` and tarball downloads, which together are the read path every install runs through. Older endpoint documentation is in `npm/registry` as an archived collection and in `npm/api-documentation`, and the fullest public account of the read path is a third-party OpenAPI file assembled from observed behaviour. `npm-registry-couchapp` was the last publicly readable server and GitHub archived it on 11 August 2021, with a deprecation notice that names the internal micro-services now serving the API. Verdaccio and cnpm implement a compatible API by matching observed behaviour, a weakness in an ecosystem with five clients in npm, yarn, pnpm, bun and Deno. Maven publishes the repository layout and the POM reference, with `maven-metadata.xml` defined by the Repository Metadata Model, so the storage format is specified. What stays de facto is the resolver’s conflict and ordering behaviour, defined by what `ComparableVersion` and the resolver in maven-artifact compute. The Gradle team derived those semantics from observed behaviour and then shipped Gradle Module Metadata alongside the POM as its own specification. Sonatype has operated Maven Central since 2008, GitHub operates npm, and each publishes what it chooses to document. ecosyste.ms maintains OpenAPI schemas for more than 25 registry APIs. Two of those registries publish an official schema themselves, crates.io and open-vsx.org, and the rest are generated from the mapping code in packages.ecosyste.ms. ### Versioning Every ecosystem has its own versioning rules, and version comparison is the least settled part of the whole business. Semantic Versioning 2.0.0 is a self-published document on semver.org by Tom Preston-Werner under CC BY 3.0, and its one IETF reference is RFC 2119, cited for MUST and SHOULD. It specifies version syntax and precedence only, so range syntax comes from each client: node-semver’s README is the operative document for npm, Cargo’s caret default is in the Cargo book, Ruby’s `~>` is in the RubyGems documentation, and Python’s are in PEP 440 and PEP 508. Ordering rules split the same way: Debian Policy section 5.6.12 gives the comparison algorithm for epoch, `upstream_version` and `debian_revision` in the policy text itself, PEP 440 does the same for Python, and Go’s pseudo-versions and `+incompatible` suffix are described in the module reference. RPM’s ordering is `rpmvercmp` inside librpm and Maven’s is `ComparableVersion` in maven-artifact, with the implementation as the reference in both cases. `univers` exists because of that spread: one library that reimplements every ecosystem’s comparison rules behind a single interface. The cross-ecosystem attempt is `vers`, from the purl project, which defines a URI syntax for version ranges together with the semantics for interpreting each notation, so an npm caret range comes out as `vers:npm/>=1.0.2|<2.0.0`. It was developed alongside purl and is due to be proposed to Ecma later in 2026, which would put ranges in the same venue as identifiers and lifecycle events. Ecma would then hold the identifier, the bill of materials, the lifecycle record and the version range, four of the pieces that have to mean the same thing in every ecosystem, within three years of TC54’s founding, while the protocol layer remains inside the ecosystems and with the registry operators.
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 05/10/2026
New hobby: trying to make deterministic versions of llm powered dependency analysis tools using the various parts of git-pkgs. Normally can get 90% of the way that and it ends up being much faster and cheaper.
001 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 04/10/2026
TIL you can end your github repo names with a dot, so the git clone url is github.com/andrew/foo..git 🙈
121 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 04/10/2026
It's Sunday evening, do you know which user agents your residential proxy scraper farms are using today?
302 0
Reposted by Andrew Nesbitt
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 03/10/2026
This Week in Package Management: 3 October 2026 nesbitt.io/2026/10/03/this-week-in-…
nesbitt.io
This Week in Package Management: 3 October 2026
Week twenty of the roundup, built from the package manager OPML feed collection and whatever I’ve posted or boosted on Mastodon. ## Releases mise 2026.10.0 requires keyless cosign bundles to match a pinned signer identity and stops GitHub attestation workflow checks accepting partial matches. 2026.9.18 added an `include` key that lets `mise.toml` pull a shared config fragment from a git repository or OCI registry, limited to tools, env, vars, hooks and aliases, with paranoid mode requiring a full commit sha or OCI digest. npm 12.2.0 accepts OIDC authentication for `npm dist-tag`, previously token-only. On the registry side, trusted publishing configurations now have an opt-in dist-tag permission, off by default, so a workflow can manage `latest`, `next` and similar tags without a long-lived token. pnpm 12.9 adds a per-registry `networkConcurrency` setting, records every installed project in the store, and stops `pnpm login` forwarding credentials in the request body to another origin on redirect. 12.8 warns when `pnpm pack` or `pnpm publish` would put a `.env` file in the tarball. RubyGems 4.0.22 keeps credentials on redirects only within the same origin. It also validates the `version` field in `Gem::Installer#verify_spec` and adds a `--source` option to `gem exec`. OpenTofu 1.13.0 ships official Windows on ARM64 packages and adds functions that reduce unknown values during planning by letting module authors assert facts beyond what OpenTofu infers. Two experiments ship with it: built-in linting, and “symbol libraries”, a reusable collection of values, functions and type aliases importable from the same sources as modules. This is the last series with 32 bit CPU releases, and it drops the WinRM provisioner. Scoop 0.6.0 searches the bucket’s git history for a versioned manifest when installing `app@version`, and auto-generates one from `autoupdate` only if that search fails. `checkver` GitHub mode now needs an explicit `github:` key to opt into the GitHub token path, the GitHub `checkver` defaults for `jsonpath` and `regex` have changed, and new installs write `scoop-install.json` and `scoop-manifest.json`, so an app’s own `install.json` and `manifest.json` are preserved. Conan 2.33.0 supports CPS component configurations and takes CPEs for a component through `extra_info`. A new `core.net.http:trust_store` conf verifies HTTPS certificates against the OS trust store, remotes accept a `force_auth` capability, and recipe and package metadata now download in parallel with regular files, where they previously downloaded afterwards. Python 3.7 support is removed. Git 2.56.0 adds `create`, `delete`, `update` and `rename` subcommands to `git refs`, and a `promisor.acceptFromServerURL` setting that governs whether the other side may add to the list of promisor remotes. The experimental `git history` command adds a `drop` subcommand, which removes a commit and replays its descendants onto the parent. Rust 1.99.0 ships Cargo 0.100.0, which disables incremental compilation by default when the `CI` environment variable is set and adds a built-in `debug` profile ahead of moving the `dev` profile toward faster iteration defaults. conda 26.9.0 schedules implicit installation of pip alongside Python for deprecation. It stays enabled in this release and becomes deprecated in 27.3; `add_pip_as_python_dependency` defaults to false from 27.9. Environments that need pip should request it explicitly. Zig 0.17.0 moves package management out of the compiler and into the build system, so `zig fetch` and the HTTP, TLS and git protocol code it uses now compile in safe mode. `zig fetch` writes to the global cache only unless `--save` is passed, `--pkg-path` and `ZIG_LOCAL_PKG_DIR` override where packages are read from, and path dependencies that escape the parent package root are rejected. Also out: * Homebrew 7.0.7 * pipx 1.17.10 * uv 0.12.22 * pnpm 11.28.3 * Athens 0.19.2 * Cabal 3.18.2.0 * Pkg.jl 1.13.1 * Maven 3.10.0 * sbt 2.0.10 and 2.1.0-M3 * Elm 0.19.3-beta * Terraform 1.16.5 * OpenTofu 1.12.7 * Docker Engine 29.9.0-rc.1 * Renovate 44.132.2 * Dependabot Core 0.398.0 ## Security LuaRocks.org published an incident report for a remote code execution in its rockspec parser. The parser called `loadstring` without restricting input to text mode, so an attacker could upload precompiled bytecode as a rockspec and escape the sandbox. The vulnerability was exploited between 9 July and 20 August, three malicious packages were uploaded on 7 August, and usernames, email addresses, bcrypt password hashes, API keys, 2FA secrets and GitHub linking tokens were exposed. LuaRocks.org has moved to new infrastructure, revoked all API keys and sessions, and removed the three packages. There is no evidence existing packages were modified. Flatpak 1.18.4 fixes six CVEs, each of which requires an already-installed malicious app. 1.19.2 includes the same fixes on the development branch. * CVE-2026-97023, privileged deletion of arbitrary files * CVE-2026-97024, privileged overwrite of arbitrary files with an empty file or a symlink to `/run/host/monitor/resolv.conf` * CVE-2026-97025, an authentication token exposed to other users when downloading from an OCI repository that requires authentication * CVE-2026-97026, loose permissions on temporary repository directories under `/var/tmp/flatpak-cache-*` * CVE-2026-97027, `.desktop` and D-Bus `.service` files now filtered against an allowlist of fields to stop denial of service and unintended interactions with host services * CVE-2026-97029, signals sent to a process group that includes a parent outside the app, which kills the desktop environment Podman 6.1.3 and 5.8.8 fix CVE-2026-94603, where `podman run` on a checkpoint image, meaning any image carrying the `io.podman.annotations.checkpoint.runtime.name` annotation, could disable all sandboxing, including the sandboxing the user specified. Both releases remove support for running checkpoint images, on the grounds that checkpoints override user-specified security configuration and are difficult to run safely. Moby 25.0.18 backports the fix for CVE-2026-17106, where the tar extraction routines in `moby/go-archive` allowed filesystem operations outside the destination directory, so anyone controlling an archive’s contents could write to arbitrary paths. Docker Engine 29.7.0 and Docker Desktop 4.86.0 include the same fix. CVE-2026-92543, fixed in Docker Engine 29.8.2, let a DNS response that paired a loopback address with an attacker-controlled address make the engine treat a registry as insecure. The insecure-registry check matched on the loopback entry while the transport layer re-dialled the hostname, so pulls reached the attacker’s server with certificate verification disabled. Digest pinning or signature verification blocks it. Python released 3.14.8, 3.13.16, 3.12.15, 3.11.17 and 3.10.22 with fixes for eight CVEs across tarfile, zipfile, SSL and urllib. 3.10.22 is the final 3.10 release. uv 0.12.22 bundles the new interpreters. Renovate published four advisories: a critical `allowedEnv` bypass and a high `allowedHeaders` bypass, both via shared presets, a high SSRF through HTTP preset URLs in `extends` or `customDatasources`, and a moderate `minimumReleaseAge` bypass when a user requests a PR rebase. All four are fixed by 44.79.0, with no backports to earlier majors. The mise releases above also close a trust bypass, where a `mise.toml` in an untrusted directory could put options inside a tool key, such as a `github:` key with `[api_url=...]` pointing at another host. mise treated the value as a plain version string, so it loaded the file before any trust check, and `mise ls`, `env`, `current`, `outdated`, `upgrade --dry-run` and `latest` then sent `GITHUB_TOKEN` to that host. Any tool key containing `[` now requires trust, and 2026.10.0 extends the same requirement to inline options in `.tool-versions`. ## Articles 15 years of Packagist counts from monolog/monolog becoming package ID 1 on 27 September 2011. Packagist now lists over 469,000 packages across 5.8 million versions, and installs have passed 201.6 billion, with more than 36 billion in 2026 so far, ahead of the 2025 total. It ran on a single personal server with 100 Mbps until April 2015, and served around 67 million installs a month by the move to AWS. One version per process (Sebastian Bergmann) works through what PHP’s one-definition-per-name rule does to Composer: every dependency resolves to a single version, and whoever introduced a conflict has to resolve it. Bergmann argues that is why PHP dependency lists stay short and version ranges stay wide. PHPUnit’s PHAR works around the rule with php-scoper, which renames bundled namespaces so `SebastianBergmann\Exporter` becomes `PHPUnitPHAR\SebastianBergmann\Exporter`. Don’t couple your Go code to GitHub (Iain Cambridge) argues for vanity module paths over `github.com/...` imports. A domain the author controls serves a `go-import` meta tag pointing at the current host, so moving the repository changes one meta tag instead of every consumer’s import statements. The example configures nginx to redirect browsers to GitHub while serving the meta tag to the Go toolchain. Git 3.0’s upcoming SHA-256 default will be a costly mistake (Scott Chacon, GitButler) argues against making SHA-256 the default object hash in Git 3.0, on the grounds that real attacks exploit distribution and social engineering rather than hash collisions. Chacon proposes signed tree-content hash headers alongside commits as an opt-in alternative that adds collision resistance and leaves the Git object format unchanged for everyone else. Seth Larson published more than ten posts from the Python Language Summit 2026, held at EuroPython in Kraków. The namespaces session is the one for packaging readers: Pablo Galindo Salgado proposed a `std` namespace for the standard library, so `import std.json` would work while `import json` keeps working indefinitely. Part of the motivation is that new stdlib module names must differ from names already taken on PyPI. `tomllib`, `graphlib` and `zoneinfo` were named that way for this reason. The session left open whether new modules should be reachable only under `std`. ## Papers Fighting Supply Chain Attacks with Effect Systems (Magnus Madsen et al., PACMPL) extends the Flix compiler with an effect-aware package manager and effect lock files, where an upgrade is accepted only if its inferred effects are a subset of the locked set. Evaluated against 51 real supply chain attacks from the Backstabbers Knife Collection, 48 would have been blocked. A Comprehensive Empirical Analysis of Patch Presence Testing (Xiaobei Zhang et al., PACMSE) builds a 561-CVE benchmark across ten C/C++ projects and runs five patch-presence tools against it. Accuracy figures in prior work count only the cases where a tool produced a result, and in practice the tools frequently fail to produce one. ## Elsewhere The PHP Foundation opened applications for 2027 contractor positions across its core development areas. The form closes on 20 October 2026. I’ll be at Open Source Summit Europe and OpenSSF Community Day in Prague, as will Renovate maintainers Sebastian Poxhofer and Jamie Tanna. GitHub added per-user daily rate limits on private vulnerability reports, with a repository-level trusted-reporter allowlist, and structured report forms configured through `.github/VULNERABILITY_REPORT.yml` using issue-form syntax. ## git-pkgs I tagged 18 repos this week: * git-pkgs v0.21.0 * codemeta v0.3.0 (new), a zero-dependency Go library for parsing `codemeta.json` and validating software metadata, which preserves source positions, unknown fields and numeric spelling * peek v0.1.0 (new), which extracts explicit claims such as an `SPDX-License-Identifier` line from files and from bounded file prefixes, including the roughly 1 KB prefixes in Software Heritage exports * archives v0.8.1 * brief v0.14.0 * clone v0.7.5 * enrichment v0.7.2 * forge v0.10.1 * licenses v0.9.0 * magic v0.5.0 * manifests v0.12.3 * outline v0.2.3 * proxy v0.9.0 * registries v0.9.3 * roles v0.1.3 * sarif v0.1.3 * scan v0.1.1 * vers v0.7.2 Send links for next week to @[email protected].
001 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 03/10/2026
This Week in Package Management: 3 October 2026 nesbitt.io/2026/10/03/this-week-in-…
nesbitt.io
This Week in Package Management: 3 October 2026
Week twenty of the roundup, built from the package manager OPML feed collection and whatever I’ve posted or boosted on Mastodon. ## Releases mise 2026.10.0 requires keyless cosign bundles to match a pinned signer identity and stops GitHub attestation workflow checks accepting partial matches. 2026.9.18 added an `include` key that lets `mise.toml` pull a shared config fragment from a git repository or OCI registry, limited to tools, env, vars, hooks and aliases, with paranoid mode requiring a full commit sha or OCI digest. npm 12.2.0 accepts OIDC authentication for `npm dist-tag`, previously token-only. On the registry side, trusted publishing configurations now have an opt-in dist-tag permission, off by default, so a workflow can manage `latest`, `next` and similar tags without a long-lived token. pnpm 12.9 adds a per-registry `networkConcurrency` setting, records every installed project in the store, and stops `pnpm login` forwarding credentials in the request body to another origin on redirect. 12.8 warns when `pnpm pack` or `pnpm publish` would put a `.env` file in the tarball. RubyGems 4.0.22 keeps credentials on redirects only within the same origin. It also validates the `version` field in `Gem::Installer#verify_spec` and adds a `--source` option to `gem exec`. OpenTofu 1.13.0 ships official Windows on ARM64 packages and adds functions that reduce unknown values during planning by letting module authors assert facts beyond what OpenTofu infers. Two experiments ship with it: built-in linting, and “symbol libraries”, a reusable collection of values, functions and type aliases importable from the same sources as modules. This is the last series with 32 bit CPU releases, and it drops the WinRM provisioner. Scoop 0.6.0 searches the bucket’s git history for a versioned manifest when installing `app@version`, and auto-generates one from `autoupdate` only if that search fails. `checkver` GitHub mode now needs an explicit `github:` key to opt into the GitHub token path, the GitHub `checkver` defaults for `jsonpath` and `regex` have changed, and new installs write `scoop-install.json` and `scoop-manifest.json`, so an app’s own `install.json` and `manifest.json` are preserved. Conan 2.33.0 supports CPS component configurations and takes CPEs for a component through `extra_info`. A new `core.net.http:trust_store` conf verifies HTTPS certificates against the OS trust store, remotes accept a `force_auth` capability, and recipe and package metadata now download in parallel with regular files, where they previously downloaded afterwards. Python 3.7 support is removed. Git 2.56.0 adds `create`, `delete`, `update` and `rename` subcommands to `git refs`, and a `promisor.acceptFromServerURL` setting that governs whether the other side may add to the list of promisor remotes. The experimental `git history` command adds a `drop` subcommand, which removes a commit and replays its descendants onto the parent. Rust 1.99.0 ships Cargo 0.100.0, which disables incremental compilation by default when the `CI` environment variable is set and adds a built-in `debug` profile ahead of moving the `dev` profile toward faster iteration defaults. conda 26.9.0 schedules implicit installation of pip alongside Python for deprecation. It stays enabled in this release and becomes deprecated in 27.3; `add_pip_as_python_dependency` defaults to false from 27.9. Environments that need pip should request it explicitly. Zig 0.17.0 moves package management out of the compiler and into the build system, so `zig fetch` and the HTTP, TLS and git protocol code it uses now compile in safe mode. `zig fetch` writes to the global cache only unless `--save` is passed, `--pkg-path` and `ZIG_LOCAL_PKG_DIR` override where packages are read from, and path dependencies that escape the parent package root are rejected. Also out: * Homebrew 7.0.7 * pipx 1.17.10 * uv 0.12.22 * pnpm 11.28.3 * Athens 0.19.2 * Cabal 3.18.2.0 * Pkg.jl 1.13.1 * Maven 3.10.0 * sbt 2.0.10 and 2.1.0-M3 * Elm 0.19.3-beta * Terraform 1.16.5 * OpenTofu 1.12.7 * Docker Engine 29.9.0-rc.1 * Renovate 44.132.2 * Dependabot Core 0.398.0 ## Security LuaRocks.org published an incident report for a remote code execution in its rockspec parser. The parser called `loadstring` without restricting input to text mode, so an attacker could upload precompiled bytecode as a rockspec and escape the sandbox. The vulnerability was exploited between 9 July and 20 August, three malicious packages were uploaded on 7 August, and usernames, email addresses, bcrypt password hashes, API keys, 2FA secrets and GitHub linking tokens were exposed. LuaRocks.org has moved to new infrastructure, revoked all API keys and sessions, and removed the three packages. There is no evidence existing packages were modified. Flatpak 1.18.4 fixes six CVEs, each of which requires an already-installed malicious app. 1.19.2 includes the same fixes on the development branch. * CVE-2026-97023, privileged deletion of arbitrary files * CVE-2026-97024, privileged overwrite of arbitrary files with an empty file or a symlink to `/run/host/monitor/resolv.conf` * CVE-2026-97025, an authentication token exposed to other users when downloading from an OCI repository that requires authentication * CVE-2026-97026, loose permissions on temporary repository directories under `/var/tmp/flatpak-cache-*` * CVE-2026-97027, `.desktop` and D-Bus `.service` files now filtered against an allowlist of fields to stop denial of service and unintended interactions with host services * CVE-2026-97029, signals sent to a process group that includes a parent outside the app, which kills the desktop environment Podman 6.1.3 and 5.8.8 fix CVE-2026-94603, where `podman run` on a checkpoint image, meaning any image carrying the `io.podman.annotations.checkpoint.runtime.name` annotation, could disable all sandboxing, including the sandboxing the user specified. Both releases remove support for running checkpoint images, on the grounds that checkpoints override user-specified security configuration and are difficult to run safely. Moby 25.0.18 backports the fix for CVE-2026-17106, where the tar extraction routines in `moby/go-archive` allowed filesystem operations outside the destination directory, so anyone controlling an archive’s contents could write to arbitrary paths. Docker Engine 29.7.0 and Docker Desktop 4.86.0 include the same fix. CVE-2026-92543, fixed in Docker Engine 29.8.2, let a DNS response that paired a loopback address with an attacker-controlled address make the engine treat a registry as insecure. The insecure-registry check matched on the loopback entry while the transport layer re-dialled the hostname, so pulls reached the attacker’s server with certificate verification disabled. Digest pinning or signature verification blocks it. Python released 3.14.8, 3.13.16, 3.12.15, 3.11.17 and 3.10.22 with fixes for eight CVEs across tarfile, zipfile, SSL and urllib. 3.10.22 is the final 3.10 release. uv 0.12.22 bundles the new interpreters. Renovate published four advisories: a critical `allowedEnv` bypass and a high `allowedHeaders` bypass, both via shared presets, a high SSRF through HTTP preset URLs in `extends` or `customDatasources`, and a moderate `minimumReleaseAge` bypass when a user requests a PR rebase. All four are fixed by 44.79.0, with no backports to earlier majors. The mise releases above also close a trust bypass, where a `mise.toml` in an untrusted directory could put options inside a tool key, such as a `github:` key with `[api_url=...]` pointing at another host. mise treated the value as a plain version string, so it loaded the file before any trust check, and `mise ls`, `env`, `current`, `outdated`, `upgrade --dry-run` and `latest` then sent `GITHUB_TOKEN` to that host. Any tool key containing `[` now requires trust, and 2026.10.0 extends the same requirement to inline options in `.tool-versions`. ## Articles 15 years of Packagist counts from monolog/monolog becoming package ID 1 on 27 September 2011. Packagist now lists over 469,000 packages across 5.8 million versions, and installs have passed 201.6 billion, with more than 36 billion in 2026 so far, ahead of the 2025 total. It ran on a single personal server with 100 Mbps until April 2015, and served around 67 million installs a month by the move to AWS. One version per process (Sebastian Bergmann) works through what PHP’s one-definition-per-name rule does to Composer: every dependency resolves to a single version, and whoever introduced a conflict has to resolve it. Bergmann argues that is why PHP dependency lists stay short and version ranges stay wide. PHPUnit’s PHAR works around the rule with php-scoper, which renames bundled namespaces so `SebastianBergmann\Exporter` becomes `PHPUnitPHAR\SebastianBergmann\Exporter`. Don’t couple your Go code to GitHub (Iain Cambridge) argues for vanity module paths over `github.com/...` imports. A domain the author controls serves a `go-import` meta tag pointing at the current host, so moving the repository changes one meta tag instead of every consumer’s import statements. The example configures nginx to redirect browsers to GitHub while serving the meta tag to the Go toolchain. Git 3.0’s upcoming SHA-256 default will be a costly mistake (Scott Chacon, GitButler) argues against making SHA-256 the default object hash in Git 3.0, on the grounds that real attacks exploit distribution and social engineering rather than hash collisions. Chacon proposes signed tree-content hash headers alongside commits as an opt-in alternative that adds collision resistance and leaves the Git object format unchanged for everyone else. Seth Larson published more than ten posts from the Python Language Summit 2026, held at EuroPython in Kraków. The namespaces session is the one for packaging readers: Pablo Galindo Salgado proposed a `std` namespace for the standard library, so `import std.json` would work while `import json` keeps working indefinitely. Part of the motivation is that new stdlib module names must differ from names already taken on PyPI. `tomllib`, `graphlib` and `zoneinfo` were named that way for this reason. The session left open whether new modules should be reachable only under `std`. ## Papers Fighting Supply Chain Attacks with Effect Systems (Magnus Madsen et al., PACMPL) extends the Flix compiler with an effect-aware package manager and effect lock files, where an upgrade is accepted only if its inferred effects are a subset of the locked set. Evaluated against 51 real supply chain attacks from the Backstabbers Knife Collection, 48 would have been blocked. A Comprehensive Empirical Analysis of Patch Presence Testing (Xiaobei Zhang et al., PACMSE) builds a 561-CVE benchmark across ten C/C++ projects and runs five patch-presence tools against it. Accuracy figures in prior work count only the cases where a tool produced a result, and in practice the tools frequently fail to produce one. ## Elsewhere The PHP Foundation opened applications for 2027 contractor positions across its core development areas. The form closes on 20 October 2026. I’ll be at Open Source Summit Europe and OpenSSF Community Day in Prague, as will Renovate maintainers Sebastian Poxhofer and Jamie Tanna. GitHub added per-user daily rate limits on private vulnerability reports, with a repository-level trusted-reporter allowlist, and structured report forms configured through `.github/VULNERABILITY_REPORT.yml` using issue-form syntax. ## git-pkgs I tagged 18 repos this week: * git-pkgs v0.21.0 * codemeta v0.3.0 (new), a zero-dependency Go library for parsing `codemeta.json` and validating software metadata, which preserves source positions, unknown fields and numeric spelling * peek v0.1.0 (new), which extracts explicit claims such as an `SPDX-License-Identifier` line from files and from bounded file prefixes, including the roughly 1 KB prefixes in Software Heritage exports * archives v0.8.1 * brief v0.14.0 * clone v0.7.5 * enrichment v0.7.2 * forge v0.10.1 * licenses v0.9.0 * magic v0.5.0 * manifests v0.12.3 * outline v0.2.3 * proxy v0.9.0 * registries v0.9.3 * roles v0.1.3 * sarif v0.1.3 * scan v0.1.1 * vers v0.7.2 Send links for next week to @[email protected].
001 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 02/10/2026
Seems like quite a lot of people starting to use github.com/git-pkgs/proxy daily feature requests and PRs coming in now.
github.com
GitHub - git-pkgs/proxy: A lightweight caching proxy for package registries.
A lightweight caching proxy for package registries. - git-pkgs/proxy
101 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 02/10/2026
git-pkgs v0.21.0 is out: fail CI on high/critical vulnerabilities with --fail-on high, get changelogs starting at your installed version, and see every dependency occurrence in outdated reports. Plus fixes for vulnerability reports across branches […]
mastodon.social
Original post on mastodon.social
000 0
Reposted by Andrew Nesbitt
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 01/10/2026
Software Heritage Identifiers nesbitt.io/2026/10/01/software-heri…
nesbitt.io
Software Heritage Identifiers
I spent Monday at the Software Heritage offices in Paris speaking at the CodeCommons plenary, and the slides are on GitHub. The talk was about connecting package identities to archived source code. Getting ready for it meant a couple of weeks poking at the SWH archive and its identifier scheme with a to-do list that kept growing, and I’ve ended up with a small pile of tools that are now feeding into ecosyste.ms, starting with the research software service. ### Software Heritage Software Heritage has been building a universal archive of source code since Inria launched the project in 2016. It crawls GitHub, GitLab, Bitbucket and a long tail of smaller forges, plus package registries and distro sources, and stores what it finds in one deduplicated Merkle DAG. As I write this that DAG holds about 30 billion source files, 23 billion directories and 6 billion commits from 445 million origins. A file that turns up in both an npm tarball and a Debian source package is stored once, addressed by the hash of its bytes, and the graph records every place it was seen. The Vault reconstructs any snapshot, commit or directory on request as a git bundle or tarball you can download, so retrieval is by content rather than by whichever URL the code was hosted at. ### SWHIDs Every object in the archive has a SoftWare Hash IDentifier of the form `swh:1:<type>:<sha1>`. The five types are `cnt` for a file’s bytes, `dir` for a directory tree, `rev` for a commit, `rel` for a tag and `snp` for a snapshot of a repository’s refs at one point in time. Optional qualifiers after a semicolon pin an origin URL, a visit, a path inside a directory or a line range inside a file. Version 1.2 of the spec was published as ISO/IEC 18670 last year, the first ISO standard for intrinsic software identifiers. A SWHID is intrinsic, computed from the bytes with no registry and no issuing authority, and because the hashes are git’s own object hashes any git checkout on your disk is already full of valid SWHIDs whether or not Software Heritage has crawled it yet. A purl like `pkg:pypi/[email protected]` is at a different corner of Zooko’s triangle: a human can read it and it’s unique within PyPI’s namespace, but resolving it to actual bytes depends on PyPI still being there to serve that release. I spend a lot of time in ecosyste.ms holding both kinds of identifier for the same software, and that mapping was the subject of the CodeCommons talk. ### swh-git The most direct way I’ve found to get code back out is swh-git, a git remote helper that adds an `swh::` transport. With `git-remote-swh` on your `PATH` you can clone by origin URL or by SWHID: git clone swh::github.com/octocat/Hello-World git clone swh::swh:1:snp:f72e9d06dd0e58236a34328f094ca894a809f230 The first form resolves to the origin’s most recent archived snapshot, and the second pins a specific one and produces the same bytes on every run. Behind the transport, the helper requests a git-bare bundle from the Vault, polls while it’s prepared (which can take several minutes for a large repository the first time), downloads it into your user cache directory, and serves the clone from there with `git upload-pack`. Fetch, `ls-remote` and shallow clones all work against the cached bundle, and push is refused since the archive is append-only from the crawler side. There’s also an HTTP proxy mode for tooling that expects a plain URL rather than a custom transport, so `git clone http://127.0.0.1:8080/github.com/octocat/Hello-World.git` does the same thing through `git http-backend`. I built this for the recovery case, where an origin URL now 404s or the forge it was on has shut down, and `git clone swh::<the old url>` gets you back to a working repository with full history and tags. The helper also accepts `rev`, `rel` and `dir` identifiers, so a directory SWHID from a paper citation or an SBOM component becomes a checkout in the same way. ### Computing SWHIDs Since a SWHID is derived from content, you can compute one anywhere you have the bytes, and I wanted that in the two languages I use most. The swhid gem covers Ruby with parsing, qualifiers and generation for all five object types, and it’s what the ecosyste.ms services use. swhid-go does the same in Go with a CLI on top and SHA-1 collision detection built in. Both are wired into the upstream conformance test suite that the SWHID working group maintains, so they’re checked against the reference vectors alongside the Python and Rust implementations. Compiling swhid-go to WebAssembly gives you swhid-wasm, a browser page that fetches a package by name from npm, PyPI, crates.io, RubyGems or pub.dev, or takes a local archive you drop onto it, then unpacks and hashes the whole tree client-side. You get content and directory SWHIDs for every file, executable bits, symlinks and duplicate detection, and the package bytes stay on your machine. Once the tree is hashed the page batch-posts the identifiers to the archive’s `/api/1/known/` endpoint to colour in which ones are already preserved, and there’s a button to submit the package’s public URL to Software Heritage for archival. Early builds of the wasm page needed a same-origin relay for that lookup, because the browser’s CORS preflight for a JSON `POST` was reaching the Anubis bot-protection layer in front of the archive and getting an HTML challenge back instead of CORS headers. I reported it and the SWH team have since adjusted the Anubis configuration so preflights pass through, and the page can now call the archive directly, though by that point the identifiers are already computed and the lookup itself is optional. ### Web API All of the above ends up calling `archive.softwareheritage.org/api/1`, which SWH document thoroughly in prose. There’s no machine-readable spec yet, though it’s something the team are interested in, so swh-openapi is my stopgap, generating an OpenAPI description from the same docstring data the published reference is built from. swh-go is a Go client generated from that with pagination, auth and rate-limit handling written by hand, and both should be retired once there’s an official spec. ### Critical package coverage With a client in hand I ran a coverage check, swh-critical, over the roughly 9,800 packages in the packages.ecosyste.ms critical set and their 7,000-odd source repositories on 23 and 24 September. Of those repositories, 71.3% had their current default-branch commit already in the archive, and 89.9% of matched release tags were present as revisions. Among the repositories whose current commit was missing, 95.1% still had an older snapshot once I checked the former URLs ecosyste.ms records across renames as well as the current one. The 46 hardest cases in the audit had no snapshot at any URL I tried and no matching release objects either, and drilling into those with full clones and tree hashes from the published package tarballs still turned up archived content for every one. Across the whole audit the pattern was older history already in the archive with only recent commits missing. I think ecosyste.ms can be most useful to Software Heritage as a partner on that last part, since the archive tracks over 445 million origins, far more than the crawler can revisit at a uniform cadence, while ecosyste.ms has dependent counts, download numbers and a criticality score for each package that give a decent signal for which repositories matter most to keep fresh. Feeding that back as a ranked stream of Save Code Now requests means the crawler’s next visit goes to the source of something with a hundred thousand dependents rather than an abandoned fork. ### science.ecosyste.ms The first place that feedback loop is running in production is science.ecosyste.ms, the ecosyste.ms service that tracks research software. For each project with a high enough science score, a background job clones the repository, computes revision and directory SWHIDs with the Ruby gem, and posts them in batches to `/api/1/known/`. Projects with objects missing from the archive get their origin submitted through Save Code Now, another job polls the visit until it completes, and any SWHID newly known after our request is recorded as a confirmed contribution. The stats page rolls those up every six hours with a JSON API alongside, and individual project pages now show SWHIDs next to the DOIs and citation metadata they already had. Research software was the right place to start because that community already cares about persistent identifiers and long-term reproducibility. ### packages.ecosyste.ms The next step is doing the same for package versions on packages.ecosyste.ms, which means computing directory SWHIDs for published tarballs as well as git checkouts and storing the purl-to-SWHID mapping as a first-class field. At that point an SBOM component like `pkg:npm/[email protected]` resolves through ecosyste.ms to a `swh:1:dir:` you can verify against the tarball you downloaded and fetch from the archive independently of npm. It also turns the one-off swh-critical audit into a rolling measurement, with coverage tracked per registry and new gaps fed back through the same Save Code Now route. ### Scanning the archive The scanners I’ve been building under git-pkgs can also treat the archive as a corpus rather than a backup, since they already run against any checkout. manifests parses package-manager manifest and lockfiles across ecosystems, licenses does fast SPDX detection against the ScanCode rule corpus, and brief reports a project’s whole toolchain and conventions as structured JSON. With swh-git in front of them the checkout comes from the archive by SWHID instead of a live forge, and any of their outputs anchored to a `swh:1:rev:` is reproducible by anyone with the same identifier. Longer term I’d like to try running these against the SWH graph dataset export directly rather than one Vault checkout at a time, which would make questions about lockfile adoption or license drift across whole registries answerable from preserved source rather than whatever happens to still be online. Software Heritage has already built the archive and standardised the identifier; what I’ve been doing is plumbing to reach it from the package-management side and to point ecosyste.ms data at the repositories where another crawl would help most. All of it is MIT or Apache-2.0 licensed, and I’d be very happy to see any of it picked up or replaced by something better.
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 01/10/2026
Software Heritage Identifiers nesbitt.io/2026/10/01/software-heri…
nesbitt.io
Software Heritage Identifiers
I spent Monday at the Software Heritage offices in Paris speaking at the CodeCommons plenary, and the slides are on GitHub. The talk was about connecting package identities to archived source code. Getting ready for it meant a couple of weeks poking at the SWH archive and its identifier scheme with a to-do list that kept growing, and I’ve ended up with a small pile of tools that are now feeding into ecosyste.ms, starting with the research software service. ### Software Heritage Software Heritage has been building a universal archive of source code since Inria launched the project in 2016. It crawls GitHub, GitLab, Bitbucket and a long tail of smaller forges, plus package registries and distro sources, and stores what it finds in one deduplicated Merkle DAG. As I write this that DAG holds about 30 billion source files, 23 billion directories and 6 billion commits from 445 million origins. A file that turns up in both an npm tarball and a Debian source package is stored once, addressed by the hash of its bytes, and the graph records every place it was seen. The Vault reconstructs any snapshot, commit or directory on request as a git bundle or tarball you can download, so retrieval is by content rather than by whichever URL the code was hosted at. ### SWHIDs Every object in the archive has a SoftWare Hash IDentifier of the form `swh:1:<type>:<sha1>`. The five types are `cnt` for a file’s bytes, `dir` for a directory tree, `rev` for a commit, `rel` for a tag and `snp` for a snapshot of a repository’s refs at one point in time. Optional qualifiers after a semicolon pin an origin URL, a visit, a path inside a directory or a line range inside a file. Version 1.2 of the spec was published as ISO/IEC 18670 last year, the first ISO standard for intrinsic software identifiers. A SWHID is intrinsic, computed from the bytes with no registry and no issuing authority, and because the hashes are git’s own object hashes any git checkout on your disk is already full of valid SWHIDs whether or not Software Heritage has crawled it yet. A purl like `pkg:pypi/[email protected]` is at a different corner of Zooko’s triangle: a human can read it and it’s unique within PyPI’s namespace, but resolving it to actual bytes depends on PyPI still being there to serve that release. I spend a lot of time in ecosyste.ms holding both kinds of identifier for the same software, and that mapping was the subject of the CodeCommons talk. ### swh-git The most direct way I’ve found to get code back out is swh-git, a git remote helper that adds an `swh::` transport. With `git-remote-swh` on your `PATH` you can clone by origin URL or by SWHID: git clone swh::github.com/octocat/Hello-World git clone swh::swh:1:snp:f72e9d06dd0e58236a34328f094ca894a809f230 The first form resolves to the origin’s most recent archived snapshot, and the second pins a specific one and produces the same bytes on every run. Behind the transport, the helper requests a git-bare bundle from the Vault, polls while it’s prepared (which can take several minutes for a large repository the first time), downloads it into your user cache directory, and serves the clone from there with `git upload-pack`. Fetch, `ls-remote` and shallow clones all work against the cached bundle, and push is refused since the archive is append-only from the crawler side. There’s also an HTTP proxy mode for tooling that expects a plain URL rather than a custom transport, so `git clone http://127.0.0.1:8080/github.com/octocat/Hello-World.git` does the same thing through `git http-backend`. I built this for the recovery case, where an origin URL now 404s or the forge it was on has shut down, and `git clone swh::<the old url>` gets you back to a working repository with full history and tags. The helper also accepts `rev`, `rel` and `dir` identifiers, so a directory SWHID from a paper citation or an SBOM component becomes a checkout in the same way. ### Computing SWHIDs Since a SWHID is derived from content, you can compute one anywhere you have the bytes, and I wanted that in the two languages I use most. The swhid gem covers Ruby with parsing, qualifiers and generation for all five object types, and it’s what the ecosyste.ms services use. swhid-go does the same in Go with a CLI on top and SHA-1 collision detection built in. Both are wired into the upstream conformance test suite that the SWHID working group maintains, so they’re checked against the reference vectors alongside the Python and Rust implementations. Compiling swhid-go to WebAssembly gives you swhid-wasm, a browser page that fetches a package by name from npm, PyPI, crates.io, RubyGems or pub.dev, or takes a local archive you drop onto it, then unpacks and hashes the whole tree client-side. You get content and directory SWHIDs for every file, executable bits, symlinks and duplicate detection, and the package bytes stay on your machine. Once the tree is hashed the page batch-posts the identifiers to the archive’s `/api/1/known/` endpoint to colour in which ones are already preserved, and there’s a button to submit the package’s public URL to Software Heritage for archival. Early builds of the wasm page needed a same-origin relay for that lookup, because the browser’s CORS preflight for a JSON `POST` was reaching the Anubis bot-protection layer in front of the archive and getting an HTML challenge back instead of CORS headers. I reported it and the SWH team have since adjusted the Anubis configuration so preflights pass through, and the page can now call the archive directly, though by that point the identifiers are already computed and the lookup itself is optional. ### Web API All of the above ends up calling `archive.softwareheritage.org/api/1`, which SWH document thoroughly in prose. There’s no machine-readable spec yet, though it’s something the team are interested in, so swh-openapi is my stopgap, generating an OpenAPI description from the same docstring data the published reference is built from. swh-go is a Go client generated from that with pagination, auth and rate-limit handling written by hand, and both should be retired once there’s an official spec. ### Critical package coverage With a client in hand I ran a coverage check, swh-critical, over the roughly 9,800 packages in the packages.ecosyste.ms critical set and their 7,000-odd source repositories on 23 and 24 September. Of those repositories, 71.3% had their current default-branch commit already in the archive, and 89.9% of matched release tags were present as revisions. Among the repositories whose current commit was missing, 95.1% still had an older snapshot once I checked the former URLs ecosyste.ms records across renames as well as the current one. The 46 hardest cases in the audit had no snapshot at any URL I tried and no matching release objects either, and drilling into those with full clones and tree hashes from the published package tarballs still turned up archived content for every one. Across the whole audit the pattern was older history already in the archive with only recent commits missing. I think ecosyste.ms can be most useful to Software Heritage as a partner on that last part, since the archive tracks over 445 million origins, far more than the crawler can revisit at a uniform cadence, while ecosyste.ms has dependent counts, download numbers and a criticality score for each package that give a decent signal for which repositories matter most to keep fresh. Feeding that back as a ranked stream of Save Code Now requests means the crawler’s next visit goes to the source of something with a hundred thousand dependents rather than an abandoned fork. ### science.ecosyste.ms The first place that feedback loop is running in production is science.ecosyste.ms, the ecosyste.ms service that tracks research software. For each project with a high enough science score, a background job clones the repository, computes revision and directory SWHIDs with the Ruby gem, and posts them in batches to `/api/1/known/`. Projects with objects missing from the archive get their origin submitted through Save Code Now, another job polls the visit until it completes, and any SWHID newly known after our request is recorded as a confirmed contribution. The stats page rolls those up every six hours with a JSON API alongside, and individual project pages now show SWHIDs next to the DOIs and citation metadata they already had. Research software was the right place to start because that community already cares about persistent identifiers and long-term reproducibility. ### packages.ecosyste.ms The next step is doing the same for package versions on packages.ecosyste.ms, which means computing directory SWHIDs for published tarballs as well as git checkouts and storing the purl-to-SWHID mapping as a first-class field. At that point an SBOM component like `pkg:npm/[email protected]` resolves through ecosyste.ms to a `swh:1:dir:` you can verify against the tarball you downloaded and fetch from the archive independently of npm. It also turns the one-off swh-critical audit into a rolling measurement, with coverage tracked per registry and new gaps fed back through the same Save Code Now route. ### Scanning the archive The scanners I’ve been building under git-pkgs can also treat the archive as a corpus rather than a backup, since they already run against any checkout. manifests parses package-manager manifest and lockfiles across ecosystems, licenses does fast SPDX detection against the ScanCode rule corpus, and brief reports a project’s whole toolchain and conventions as structured JSON. With swh-git in front of them the checkout comes from the archive by SWHID instead of a live forge, and any of their outputs anchored to a `swh:1:rev:` is reproducible by anyone with the same identifier. Longer term I’d like to try running these against the SWH graph dataset export directly rather than one Vault checkout at a time, which would make questions about lockfile adoption or license drift across whole registries answerable from preserved source rather than whatever happens to still be online. Software Heritage has already built the archive and standardised the identifier; what I’ve been doing is plumbing to reach it from the package-management side and to point ecosyste.ms data at the repositories where another crawl would help most. All of it is MIT or Apache-2.0 licensed, and I’d be very happy to see any of it picked up or replaced by something better.
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 01/10/2026
brief v0.14.0 is out: CITATION.cff and CodeMeta metadata, source manifest paths for dependencies, better Ruby/Python/Rust project detection, TinyGo support, and compact npm lockfile fixes. github.com/git-pkgs/brief/releases/…
github.com
Release v0.14.0 · git-pkgs/brief
Changelog 5f53947 Add and align CI security and dependency automation 8e75365 Apply gopls modernize fixes (#192) 73f926f Bump github.com/git-pkgs/archives from 0.7.0 to 0.7.1 (#191) e635e97 Bump g...
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 01/10/2026
git-pkgs proxy v0.9.0 is out with npm audit support, version denylists and multiple Debian archives. It fixes NuGet cooldown enforcement and concurrent download failures, and refreshes SPDX license data. github.com/git-pkgs/proxy/releases/…
github.com
Release v0.9.0 · git-pkgs/proxy
Changelog c1f420a Add and align CI security and dependency automation 73a9863 Assert omitted Helm releases are not downloadable 8d3dacf Bump azure/setup-helm from 4.3.1 to 5.0.1 (#332) f0580d9 Bum...
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 29/09/2026
What a menace
Basil the black toy poodle reaching over the arm of the chair
001 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 27/09/2026
Luarocks having a a bad day: luarocks.org/security-incident-sept… Don't sleep on TUF: nesbitt.io/2026/05/24/signing-is-fo…
luarocks.org
LuaRocks Security Incident September 2026
Comments
100 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 26/09/2026
Was much easier to get git-pkgs modules running in the browser as wasm than expected!
git-pkgs in the browser via wasm
100 0
Reposted by Andrew Nesbitt
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 26/09/2026
This Week in Package Management: 26 September 2026 nesbitt.io/2026/09/26/this-week-in-…
nesbitt.io
This Week in Package Management: 26 September 2026
Week nineteen of the roundup, built from the package manager OPML feed collection and whatever I’ve posted or boosted on Mastodon. ## Releases pnpm 12.6 adds an `autoDedupe` setting that resolves compatible dependency versions to a single one during install, and `pnpm add --save-types` for the matching `@types/*` package. 12.7 has the global node shim read `.nvmrc` and `.node-version` when `devEngines.runtime` is unset, and adds `pnpm publish --publish-wait-timeout` to block until a published package is available before dependents publish. RubyGems 4.1.0.beta1 adds content-addressable gems, an opt-in OS credential store for gem and Bundler credentials, ML-DSA post-quantum signatures for the signed-gem workflow, and a `--cooldown` flag on `gem install`, `update` and `outdated`. npm 12.1.0 supports `read-write-stage-only` granular access tokens for staged publishing, and `npm stage` reports the status of packages held in staging. A `--provenance-file` argument now takes precedence over OIDC-generated provenance. Poetry 2.5.0 adds an `installer.builtin-uninstall` setting that removes packages itself instead of calling pip, supports Python 3.15, and stops sending credentials configured for an HTTPS repository over plain HTTP. 2.5.1 fixes a `TypeError` in the new uninstaller. Terraform 1.17.0-beta2 allows variables and locals in provider requirements and adds a `-minimal-refresh` planning option that only refreshes resources with proposed changes. Terraform Policy is now generally available and no longer requires the experimental-features flag. Windows Package Manager 1.29.380 adds an experimental source priority setting: sources can be assigned a numeric priority via `winget source add` or `source edit` and are ordered by it in results. mise 2026.9.14 lets registry entries require a verified GitHub attestation before a tool installs, and fetches release metadata for any public GitHub repo from mise-versions rather than the GitHub API. Also out: * Homebrew 7.0.6 * pipx 1.17.6 * Hatchling 1.32.4 * uv 0.12.19 * pnpm 11.28 * Yarn 4.18.1 * asdf 0.20.2 * sbt 2.1.0-M2 * Maven 4.0.0-rc-7 * Gradle 9.8.0 * vcpkg 2026-09-26 * DNF5 5.4.6.0 * Terraform 1.16.4 * Harbor 2.15.3-rc2 * Renovate 44.115.10 * Dependabot Core 0.397.0 * setup-uv 10.2.0 * diffoscope 331 ## Security The Rust security response WG reported that Miri wrote every environment variable to `target/`, so caching that directory in GitHub Actions could expose job secrets to pull requests that read from the cache. The nightly dated 2026-09-22 restricts persisted variables to `CARGO_*` (excluding `CARGO_*_TOKEN`) and `OUT_DIR`; the post recommends clearing existing caches and rotating any secrets that were in scope. uv 0.12.18 fixes GHSA-2cv4-cqwr-gwf7, a path traversal during wheel installation on Windows. It also adds `--check` and `--output-format json` to `uv pip install` and `uv pip sync`, so planned changes can be reported while leaving the environment unchanged. Flatpak 1.18.3 updates its vendored bubblewrap to 0.12.0 for CVE-2026-87766, where sandbox setup could follow a parent symlink through `/oldroot` to write files on the host, and its vendored xdg-dbus-proxy to 0.1.8 for CVE-2026-93676, where D-Bus broadcast filtering ignored the configured path, interface and member restrictions. ## Elsewhere The Rust project announced Scott Schafer as a full-time Maintainer in Residence for the Cargo team, funded through the Rust Foundation Maintainers Fund with additional money from the Rust Leadership Council’s Project Priorities budget and AWS. Separately the Rust Foundation added CodSpeed, Haevek and Perplexity as Silver members and the Software Stewardship Lab as an Associate member. Jamie Tanna reviewed his first year as Renovate project lead: 1,813 releases, managers up from 110 to 118, datasources from 76 to 82, and external commits up 48% in the first half of 2026. Discussion-forum help requests fell 43% over the same period as users turned to LLM tools instead. Josh Bressers interviewed Daniel Stenberg and Stefan Eissing about curl’s month-long pause on accepting vulnerability reports and the volume of AI-generated submissions that prompted it. Farid Zakaria wrote up omnibin, a FUSE filesystem that presents every binary nixpkgs has shipped since 2013, 881,933 in total, by looking up store paths in Hydra’s published metadata and fetching them on first access; a cold `[email protected]` start takes about 2.7 seconds. TrustBOM: A Scalable Architecture for Confidentiality-Preserving SBOMs Across Organizations (Nguyen et al., arXiv) proposes a CI/CD-integrated attestation scheme in which a supplier proves that a given vulnerability or restricted licence is absent from its software while keeping the dependency graph private. Git 2.56.0-rc2 was tagged. ## git-pkgs I tagged eight repos this week: * citation v0.1.0 (new), a pure-Go library for parsing and validating `CITATION.cff` files that preserves source positions, unknown fields and numeric spelling * scan v0.1.0 (new), a pure-Go library that matches many regular expressions against byte blocks by compiling patterns into shared literal filters and regex automata along Hyperscan lines * secrets v0.1.0 (new), which scans Git history for leaked credentials by running the Betterleaks rule corpus over every blob and attributing findings to the commits and paths that introduced them * spam v0.1.0 (new), an offline library for measuring promotional text in package manifests and READMEs * archives v0.8.0 * clone v0.7.4 * history v0.1.1 * roles v0.1.1 Send links for next week to @[email protected].
041 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 26/09/2026
This Week in Package Management: 26 September 2026 nesbitt.io/2026/09/26/this-week-in-…
nesbitt.io
This Week in Package Management: 26 September 2026
Week nineteen of the roundup, built from the package manager OPML feed collection and whatever I’ve posted or boosted on Mastodon. ## Releases pnpm 12.6 adds an `autoDedupe` setting that resolves compatible dependency versions to a single one during install, and `pnpm add --save-types` for the matching `@types/*` package. 12.7 has the global node shim read `.nvmrc` and `.node-version` when `devEngines.runtime` is unset, and adds `pnpm publish --publish-wait-timeout` to block until a published package is available before dependents publish. RubyGems 4.1.0.beta1 adds content-addressable gems, an opt-in OS credential store for gem and Bundler credentials, ML-DSA post-quantum signatures for the signed-gem workflow, and a `--cooldown` flag on `gem install`, `update` and `outdated`. npm 12.1.0 supports `read-write-stage-only` granular access tokens for staged publishing, and `npm stage` reports the status of packages held in staging. A `--provenance-file` argument now takes precedence over OIDC-generated provenance. Poetry 2.5.0 adds an `installer.builtin-uninstall` setting that removes packages itself instead of calling pip, supports Python 3.15, and stops sending credentials configured for an HTTPS repository over plain HTTP. 2.5.1 fixes a `TypeError` in the new uninstaller. Terraform 1.17.0-beta2 allows variables and locals in provider requirements and adds a `-minimal-refresh` planning option that only refreshes resources with proposed changes. Terraform Policy is now generally available and no longer requires the experimental-features flag. Windows Package Manager 1.29.380 adds an experimental source priority setting: sources can be assigned a numeric priority via `winget source add` or `source edit` and are ordered by it in results. mise 2026.9.14 lets registry entries require a verified GitHub attestation before a tool installs, and fetches release metadata for any public GitHub repo from mise-versions rather than the GitHub API. Also out: * Homebrew 7.0.6 * pipx 1.17.6 * Hatchling 1.32.4 * uv 0.12.19 * pnpm 11.28 * Yarn 4.18.1 * asdf 0.20.2 * sbt 2.1.0-M2 * Maven 4.0.0-rc-7 * Gradle 9.8.0 * vcpkg 2026-09-26 * DNF5 5.4.6.0 * Terraform 1.16.4 * Harbor 2.15.3-rc2 * Renovate 44.115.10 * Dependabot Core 0.397.0 * setup-uv 10.2.0 * diffoscope 331 ## Security The Rust security response WG reported that Miri wrote every environment variable to `target/`, so caching that directory in GitHub Actions could expose job secrets to pull requests that read from the cache. The nightly dated 2026-09-22 restricts persisted variables to `CARGO_*` (excluding `CARGO_*_TOKEN`) and `OUT_DIR`; the post recommends clearing existing caches and rotating any secrets that were in scope. uv 0.12.18 fixes GHSA-2cv4-cqwr-gwf7, a path traversal during wheel installation on Windows. It also adds `--check` and `--output-format json` to `uv pip install` and `uv pip sync`, so planned changes can be reported while leaving the environment unchanged. Flatpak 1.18.3 updates its vendored bubblewrap to 0.12.0 for CVE-2026-87766, where sandbox setup could follow a parent symlink through `/oldroot` to write files on the host, and its vendored xdg-dbus-proxy to 0.1.8 for CVE-2026-93676, where D-Bus broadcast filtering ignored the configured path, interface and member restrictions. ## Elsewhere The Rust project announced Scott Schafer as a full-time Maintainer in Residence for the Cargo team, funded through the Rust Foundation Maintainers Fund with additional money from the Rust Leadership Council’s Project Priorities budget and AWS. Separately the Rust Foundation added CodSpeed, Haevek and Perplexity as Silver members and the Software Stewardship Lab as an Associate member. Jamie Tanna reviewed his first year as Renovate project lead: 1,813 releases, managers up from 110 to 118, datasources from 76 to 82, and external commits up 48% in the first half of 2026. Discussion-forum help requests fell 43% over the same period as users turned to LLM tools instead. Josh Bressers interviewed Daniel Stenberg and Stefan Eissing about curl’s month-long pause on accepting vulnerability reports and the volume of AI-generated submissions that prompted it. Farid Zakaria wrote up omnibin, a FUSE filesystem that presents every binary nixpkgs has shipped since 2013, 881,933 in total, by looking up store paths in Hydra’s published metadata and fetching them on first access; a cold `[email protected]` start takes about 2.7 seconds. TrustBOM: A Scalable Architecture for Confidentiality-Preserving SBOMs Across Organizations (Nguyen et al., arXiv) proposes a CI/CD-integrated attestation scheme in which a supplier proves that a given vulnerability or restricted licence is absent from its software while keeping the dependency graph private. Git 2.56.0-rc2 was tagged. ## git-pkgs I tagged eight repos this week: * citation v0.1.0 (new), a pure-Go library for parsing and validating `CITATION.cff` files that preserves source positions, unknown fields and numeric spelling * scan v0.1.0 (new), a pure-Go library that matches many regular expressions against byte blocks by compiling patterns into shared literal filters and regex automata along Hyperscan lines * secrets v0.1.0 (new), which scans Git history for leaked credentials by running the Betterleaks rule corpus over every blob and attributing findings to the commits and paths that introduced them * spam v0.1.0 (new), an offline library for measuring promotional text in package manifests and READMEs * archives v0.8.0 * clone v0.7.4 * history v0.1.1 * roles v0.1.1 Send links for next week to @[email protected].
041 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 26/09/2026
On track for @ecosystems to hit 2 billion requests serviced in September 😰
010 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 26/09/2026
Experimenting with Bazel for graphing the dependencies within different git-pkgs repos: github.com/git-pkgs/bazel
graphiz visualisation of the dependency graph of git-pkgs modules
020 0
Reposted by Andrew Nesbitt
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 24/09/2026
Package Manager Sandboxing nesbitt.io/2026/09/24/package-manag…
nesbitt.io
Package Manager Sandboxing
Homebrew 7.0.0 shipped on September 13th with “stronger sandboxing” in the opening line of the release notes. Installation is being split into a fetch phase that has network access and writable caches, and an install phase that runs offline with read-only caches. Sandboxed builds are blocked from reading your home directory by default. Cask install hooks run confined, and a cask sandbox escape via LaunchServices was closed in the same release by denying app launching, Mach services, and Unix socket connections. Formula `post_install` and cask flight blocks, which are arbitrary Ruby today, are deprecated in favour of declarative `*_steps` delivered as signed data, with a removal deadline of December 2027. Homebrew, which I help maintain, has run macOS formula builds under `sandbox-exec` since 2015. The last four months turned that from a build-hygiene measure into a stated security programme. 6.0.0 in June brought a Linux build sandbox based on Bubblewrap and made third-party taps require explicit trust before their Ruby is evaluated. By July the Bubblewrap implementation had been replaced with Landlock, which is built into the kernel and works inside unprivileged Docker, and by August Bubblewrap was removed. The 7.0.0 deprecation table lists the Linux sandbox opt-out variable as removed, with “no replacement opt-out”. A pull request opened four days before the release extends the sandbox to archive extraction and disk-image handling, and sandbox rule changes now require security review. “Tap trust remains the primary protection against malicious third-party casks; sandboxing mainly limits accidental damage and adds installation safeguards. It cannot make untrusted software safe to run,” per the release notes. Vendor `.pkg` installers still execute outside the sandbox, and installed applications run with your privileges. Install-time code can be gated (an allowlist controls whether it runs), confined (a sandbox restricts what it can reach), or replaced with data that is interpreted rather than executed. The past year’s allowlist rollout was gating. The sandbox proposals now open across issue trackers are confinement, and Homebrew’s `*_steps` migration pairs confinement with replacement. All three responses leave the same job open: validating the confined phase’s output. ## Agents Homebrew’s sandbox mechanisms come from the same small set of primitives the LLM coding agent vendors adopted over the past year. Claude Code’s sandboxed bash tool uses Seatbelt on macOS and bubblewrap on Linux, open-sourced as sandbox-runtime. Codex CLI uses Seatbelt and Landlock plus seccomp, and OpenAI built a custom restricted-token sandbox for Windows after evaluating and rejecting AppContainer. Cursor’s agent terminal uses Seatbelt and Landlock and runs the Linux sandbox inside WSL2 on Windows. Gemini CLI offers Seatbelt profiles or a container. The motivation is the one package manager maintainers cite: these tools run unreviewed code, and asking permission each time stopped working. Anthropic reports that users approve about 93% of permission prompts. The two problems overlap beyond sharing a mechanism, because agents install packages. The Shai-Hulud worm that hit npm in September 2025 spread through postinstall scripts, and one of its persistence tricks was writing a hook into Claude Code’s settings file so it survived cache cleanup with the agent’s privileges. The nx compromise a month earlier shipped a postinstall payload that attempted to use locally installed AI tools to scan for credentials. Mandiant has since reported an attacker hijacking a coding assistant session and spreading Shai-Hulud across roughly 100 internal repositories through poisoned package recommendations; an agent that installs dependencies on your behalf multiplies both the install rate and the blast radius. The crossover back into package managers is explicit in Homebrew’s `brew sandbox-exec`, which exposes its formula sandbox for arbitrary commands, and in its nested-sandbox handling, which exists, per the code comment, for running brew “inside an existing macOS sandbox (e.g. an agent’s)”. pnpm’s lead maintainer opened an issue in August proposing to wrap dependency lifecycle scripts in bubblewrap or Landlock on Linux and Seatbelt on macOS, the agent vendors’ exact stack, and the issue body ends with the note that it was written by an agent. A Deno maintainer’s hardening proposal from July names Landlock, seccomp, and Seatbelt as the planned follow-up. ## Shipped The list of package managers with OS-level confinement on by default is short, and most of it predates the agents. opam has sandboxed by default since 2.0 in 2018: every package’s build and install commands run under bubblewrap on Linux with the network cut and writes limited to the build directory, and under sandbox-exec on macOS with a deny-write, deny-network policy. Downloads happen outside the sandbox, which is the same fetch/build split Homebrew is now migrating to. opam on Windows runs unsandboxed, and this month opam’s maintainers opened an issue to investigate Landlock as a bubblewrap replacement, for the same Docker-compatibility reasons Homebrew switched. Swift Package Manager compiles and runs `Package.swift` manifests inside a Seatbelt sandbox, and SE-0303 and SE-0332 gave plugins a no-network, temp-writes-only sandbox with declared permissions on top. The implementation file states what happens elsewhere: “On platforms that don’t support sandboxing, the command line is returned unmodified.” On Linux the sandbox is a no-op, a gap flagged in the tracker and acknowledged in the accepted proposal text. Nix has run Linux builds in namespaces by default since 2.2 in 2019, and Guix builds in an equivalent isolated environment. Both projects document why: a 2024 Nix advisory states the sandbox “is not primarily intended as a security mechanism, but as an aid to improve reproducibility and purity of Nix builds”, and a 2025 pair of CVEs let a local user escalate through the build users of Nix, Lix, and Guix alike. The macOS Nix sandbox exists and is still off by default. Bazel is in the same category: build actions run in a namespace sandbox on Linux and under sandbox-exec on macOS, restricted to their declared inputs, the strictest read confinement in this section, with reproducibility as the stated goal. The oldest example is Gentoo’s Portage `sandbox`, an LD_PRELOAD shim from the early 2000s whose own README calls it a QA measure, since static binaries and anything that clears the environment bypass it. Alongside it, Portage’s default FEATURES now include network, PID, and IPC namespace isolation for ebuild phases, and those are kernel boundaries. apt splits the same way: download methods have run as a dedicated `_apt` user since apt 1.1, while the seccomp filter added in 1.6 has been disabled by default since 2018 for compatibility. dpkg maintainer scripts run as root, and confinement so far amounts to a wiki ideas page. pacman 7.0 (2024) runs downloads as a dedicated user under Landlock and seccomp, a narrower confinement than the build sandboxes above, and 7.1 tightened it with syscall restrictions and finer-grained configuration. Alpine’s `abuild rootbld` builds packages in a bubblewrap sandbox where networking is granted only to packages declaring `options=net`, though it is opt-in. mise shipped opt-in Landlock and Seatbelt sandboxing for its task runner this year. RPM 4.20 added an unshare plugin that can strip network and filesystem access from scriptlets, and it ships disabled in every distribution. CocoaPods shipped `sandbox-pod` in 2013, a wrapper that ran the whole pod install under `sandbox-exec`. The generated profile still contains `(allow network-outbound)` with a “TODO make this stricter if possible” comment, the revisit issue was closed by a stale bot in 2017, and the binary, shipped thirteen years before the current proposals and long abandoned, is still listed in the gemspec. Deno is the only JavaScript package installer with any confinement, and its deny-by-default permission model is enforced in-process by the runtime rather than by the OS, with FFI as a documented way around it and a steady stream of permission-bypass advisories. The maintainers concede in their own hardening issue that an approved npm lifecycle script currently “executes with essentially full host access”, because the `node` shim inside it spawns `deno run -A`. ## Allowlists The run of supply chain attacks from nx through Shai-Hulud 2.0 produced a lot of shipped security work in JavaScript, all of it controlling which code runs rather than confining it. Every major client now blocks dependency lifecycle scripts by default behind an allowlist: pnpm led in January 2025, Bun had gated scripts since 2023, Yarn flipped the default in April 2026, and npm 12 followed in July. Cooldowns on newly published versions went from a proposal to on-by-default at pnpm, Yarn, and Deno within about a year, with most other ecosystems shipping opt-in equivalents. An RFC titled “Make npm install scripts opt-in” was opened in November 2021, collected around 369 thumbs-up, and stayed open for four and a half years before being closed in favour of the 2026 RFC that npm 12 implements. GitHub’s immediate response to Shai-Hulud was entirely credential and publishing hardening; the default flip on scripts came eight months after the worm and five years after the original RFC. I surveyed the allowlist mechanisms in June; an allowlist controls which packages get to run code, while a sandbox limits what that code can reach once it runs. The pnpm sandbox issue makes the case for the second axis directly: an allowlist is binary, and most packages with build scripts need to compile something in their own directory, which is a permission you can grant while withholding your SSH keys and the network; approving `esbuild`’s postinstall today extends that trust to every future version of it. ## Proposals The open proposals all date from the last fourteen months and specify the same primitives. Beyond pnpm’s and Deno’s, RubyGems has a December proposal to split `bundle install` into a download phase in which only Bundler’s own code runs, and an install phase that could run sandboxed with credentials stripped, and it has a maintainer in support: “I think this makes sense.” Spack’s April issue proposes Landlock and Seatbelt applied in-process between fetch and build, on a tracker whose original sandbox request from 2017 opened with “I could easily sneak a `rm -rf ~` into a package.” Arch has a draft merge request giving install scriptlets a private network namespace, which CachyOS already ships. Cargo’s sandbox issue has been open since 2018. The intervening years produced watt, Cackle, a pre-RFC from dtolnay written after serde_derive briefly shipped a precompiled binary, and an official 2024 project goal that ended with a specific negative result: WASI lacks process spawning, and build scripts exist to spawn `pkg-config`, C compilers, and `git`, so the WebAssembly approach fails. Then in August 2026 the arrayref attack delivered a typosquatted proc-macro dependency whose `build.rs` downloaded and ran a remote binary, with infrastructure Wiz links to DPRK campaigns. The issue filed in response was closed the same day as a duplicate of the 2024 allowlist thread. Zig’s proposal, from Andrew Kelley himself, is the most radical design on any tracker, compiling every `build.zig` to WebAssembly so it can only emit a build graph as data, on top of a fetch step that is already inert, and it has been open since January 2023. pip’s “Sandbox the running of setup.py” was opened in 2017 by a PyPA maintainer and cites Homebrew’s `sandbox.rb` as the model to copy. It is still open, along with a 2022 privilege-drop issue and a 2026 AppArmor one. Poetry’s maintainers gave the flattest refusal in the survey: a post-xz request for Landlock or seccomp self-sandboxing was closed as out of scope on portability grounds. uv’s threat model places the local machine inside the trust boundary and leaves confinement out of scope, and its maintainers decline on principle to add install hooks in the first place. The only Python-adjacent tool with a sandbox on its public roadmap is pixi, which already ships conda link scripts disabled by default behind a setting whose opt-in value is spelled `insecure`. Gradle’s sandbox mode issue has been open since 2019, Maven’s security page states that “the Maven security model assumes you trust the pom.xml” and isolation is your job, and JEP 486 permanently disabled the Security Manager in JDK 24, which removed the platform’s in-process sandbox primitive in the same year demand for one returned. NuGet’s 2020 issue about warning on code execution in MSBuild target files got a maintainer reply that removing it “will break many packages”, and was revived this July citing Shai-Hulud, with a commenter pointing at Yarn as the existence proof that fail-closed defaults are survivable. The C++ managers are absent from every category above: Conan recipes and vcpkg portfiles run arbitrary Python and CMake at install time, and I found no sandbox proposal on either tracker. ## Removal A second strategy has a better shipping record than sandboxing: removing the code execution entirely. Go and Elm omitted install hooks from the start. NuGet deleted `install.ps1` with PackageReference in 2017, though MSBuild targets from packages still execute at build time, which real malware has used. Composer runs only the root project’s scripts and put plugins behind an allowlist in 2021. Julia’s Artifacts system replaced most `build.jl` usage with declarative content-addressed downloads. CPAN’s practical mitigation is `x_static_install`, which skips executing `Makefile.PL` for pure-Perl distributions. Cabal’s Hooks build type narrows arbitrary `Setup.hs` replacement to named hook points. The distributions are doing the same for scriptlets, with Fedora replacing useradd scripts with declarative sysusers.d metadata and Arch surveying scriptlet usage with declarative hooks as the goal. Homebrew’s `*_steps` migration combines removal with confinement: the hook becomes signed data, and the remaining executable steps run inside the sandbox. Dart is the counterexample: pub’s install step historically consisted of placing files on disk. The native-assets build hooks stabilised this year add execution to that path, deferred to build time, in an environment the docs describe as semi-hermetic, with reproducibility as the sole stated goal. ## Primitives 2026’s proposals name the same primitives because few exist. On Linux, Landlock is in default kernels across the major distributions, runs unprivileged without a daemon or container runtime, and versions its ABI so a client can apply whatever protections the running kernel offers, which is the compatibility posture a package manager needs. Homebrew, pacman, and mise ship it. opam and Spack have open proposals to adopt it, and every agent vendor’s Linux sandbox is built on Landlock, namespaces, or both. On macOS, Homebrew, Claude Code, and Chrome all run on Seatbelt, which Apple deprecated in 2016 and has neither removed nor replaced, a situation developers have formally asked Apple to resolve. Windows lacks a directly comparable primitive, which is why Codex built a custom sandbox from restricted tokens, Cursor and Claude Code confine through WSL2, and the pnpm proposal may add Windows support only later. The agent problem and the package manager problem meet in CI, where a GitHub-hosted Actions job gets a virtual machine of its own and isolation ends at that boundary: every `uses:` step (itself a package install) and every package manager invoked inside the job shares the runner’s filesystem, environment, and secrets. The VM protects GitHub’s infrastructure, and everything the job values, secrets included, is inside it, so an install script runs with the same reach as the workflow that invoked it. Self-hosted runners are frequently persistent and shared, which removes even the per-job boundary. The shipped control is an allowlist over which actions may run, and confinement exists as Harden-Runner, a third-party agent that monitors and filters runner egress. CI is also where kernel sandboxes compose worst: inside a `container:` job, bubblewrap fails for want of privileged namespaces (opam has had the issue open since 2020), which is why Homebrew switched to Landlock and why Spack’s proposal applies restrictions in-process. The nx compromise started this way, with a workflow injection leaking the npm token that published the malicious versions. The open boundary is the one I keep coming back to from the threat model work: the hand-off. A sandboxed build that writes an install manifest, a cache entry, or a step list which the package manager then acts on with full privileges has moved the trust decision to whatever validates that output, and Homebrew’s LaunchServices escape was a hand-off bug. The removal strategy is one answer: a signed step list or a build graph emitted as data has a schema, and the package manager interprets it instead of executing it. The proposals now open at pnpm, RubyGems, Deno, and Spack still have to specify what validates a sandboxed build’s output.
112 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 24/09/2026
Package Manager Sandboxing nesbitt.io/2026/09/24/package-manag…
nesbitt.io
Package Manager Sandboxing
Homebrew 7.0.0 shipped on September 13th with “stronger sandboxing” in the opening line of the release notes. Installation is being split into a fetch phase that has network access and writable caches, and an install phase that runs offline with read-only caches. Sandboxed builds are blocked from reading your home directory by default. Cask install hooks run confined, and a cask sandbox escape via LaunchServices was closed in the same release by denying app launching, Mach services, and Unix socket connections. Formula `post_install` and cask flight blocks, which are arbitrary Ruby today, are deprecated in favour of declarative `*_steps` delivered as signed data, with a removal deadline of December 2027. Homebrew, which I help maintain, has run macOS formula builds under `sandbox-exec` since 2015. The last four months turned that from a build-hygiene measure into a stated security programme. 6.0.0 in June brought a Linux build sandbox based on Bubblewrap and made third-party taps require explicit trust before their Ruby is evaluated. By July the Bubblewrap implementation had been replaced with Landlock, which is built into the kernel and works inside unprivileged Docker, and by August Bubblewrap was removed. The 7.0.0 deprecation table lists the Linux sandbox opt-out variable as removed, with “no replacement opt-out”. A pull request opened four days before the release extends the sandbox to archive extraction and disk-image handling, and sandbox rule changes now require security review. “Tap trust remains the primary protection against malicious third-party casks; sandboxing mainly limits accidental damage and adds installation safeguards. It cannot make untrusted software safe to run,” per the release notes. Vendor `.pkg` installers still execute outside the sandbox, and installed applications run with your privileges. Install-time code can be gated (an allowlist controls whether it runs), confined (a sandbox restricts what it can reach), or replaced with data that is interpreted rather than executed. The past year’s allowlist rollout was gating. The sandbox proposals now open across issue trackers are confinement, and Homebrew’s `*_steps` migration pairs confinement with replacement. All three responses leave the same job open: validating the confined phase’s output. ## Agents Homebrew’s sandbox mechanisms come from the same small set of primitives the LLM coding agent vendors adopted over the past year. Claude Code’s sandboxed bash tool uses Seatbelt on macOS and bubblewrap on Linux, open-sourced as sandbox-runtime. Codex CLI uses Seatbelt and Landlock plus seccomp, and OpenAI built a custom restricted-token sandbox for Windows after evaluating and rejecting AppContainer. Cursor’s agent terminal uses Seatbelt and Landlock and runs the Linux sandbox inside WSL2 on Windows. Gemini CLI offers Seatbelt profiles or a container. The motivation is the one package manager maintainers cite: these tools run unreviewed code, and asking permission each time stopped working. Anthropic reports that users approve about 93% of permission prompts. The two problems overlap beyond sharing a mechanism, because agents install packages. The Shai-Hulud worm that hit npm in September 2025 spread through postinstall scripts, and one of its persistence tricks was writing a hook into Claude Code’s settings file so it survived cache cleanup with the agent’s privileges. The nx compromise a month earlier shipped a postinstall payload that attempted to use locally installed AI tools to scan for credentials. Mandiant has since reported an attacker hijacking a coding assistant session and spreading Shai-Hulud across roughly 100 internal repositories through poisoned package recommendations; an agent that installs dependencies on your behalf multiplies both the install rate and the blast radius. The crossover back into package managers is explicit in Homebrew’s `brew sandbox-exec`, which exposes its formula sandbox for arbitrary commands, and in its nested-sandbox handling, which exists, per the code comment, for running brew “inside an existing macOS sandbox (e.g. an agent’s)”. pnpm’s lead maintainer opened an issue in August proposing to wrap dependency lifecycle scripts in bubblewrap or Landlock on Linux and Seatbelt on macOS, the agent vendors’ exact stack, and the issue body ends with the note that it was written by an agent. A Deno maintainer’s hardening proposal from July names Landlock, seccomp, and Seatbelt as the planned follow-up. ## Shipped The list of package managers with OS-level confinement on by default is short, and most of it predates the agents. opam has sandboxed by default since 2.0 in 2018: every package’s build and install commands run under bubblewrap on Linux with the network cut and writes limited to the build directory, and under sandbox-exec on macOS with a deny-write, deny-network policy. Downloads happen outside the sandbox, which is the same fetch/build split Homebrew is now migrating to. opam on Windows runs unsandboxed, and this month opam’s maintainers opened an issue to investigate Landlock as a bubblewrap replacement, for the same Docker-compatibility reasons Homebrew switched. Swift Package Manager compiles and runs `Package.swift` manifests inside a Seatbelt sandbox, and SE-0303 and SE-0332 gave plugins a no-network, temp-writes-only sandbox with declared permissions on top. The implementation file states what happens elsewhere: “On platforms that don’t support sandboxing, the command line is returned unmodified.” On Linux the sandbox is a no-op, a gap flagged in the tracker and acknowledged in the accepted proposal text. Nix has run Linux builds in namespaces by default since 2.2 in 2019, and Guix builds in an equivalent isolated environment. Both projects document why: a 2024 Nix advisory states the sandbox “is not primarily intended as a security mechanism, but as an aid to improve reproducibility and purity of Nix builds”, and a 2025 pair of CVEs let a local user escalate through the build users of Nix, Lix, and Guix alike. The macOS Nix sandbox exists and is still off by default. Bazel is in the same category: build actions run in a namespace sandbox on Linux and under sandbox-exec on macOS, restricted to their declared inputs, the strictest read confinement in this section, with reproducibility as the stated goal. The oldest example is Gentoo’s Portage `sandbox`, an LD_PRELOAD shim from the early 2000s whose own README calls it a QA measure, since static binaries and anything that clears the environment bypass it. Alongside it, Portage’s default FEATURES now include network, PID, and IPC namespace isolation for ebuild phases, and those are kernel boundaries. apt splits the same way: download methods have run as a dedicated `_apt` user since apt 1.1, while the seccomp filter added in 1.6 has been disabled by default since 2018 for compatibility. dpkg maintainer scripts run as root, and confinement so far amounts to a wiki ideas page. pacman 7.0 (2024) runs downloads as a dedicated user under Landlock and seccomp, a narrower confinement than the build sandboxes above, and 7.1 tightened it with syscall restrictions and finer-grained configuration. Alpine’s `abuild rootbld` builds packages in a bubblewrap sandbox where networking is granted only to packages declaring `options=net`, though it is opt-in. mise shipped opt-in Landlock and Seatbelt sandboxing for its task runner this year. RPM 4.20 added an unshare plugin that can strip network and filesystem access from scriptlets, and it ships disabled in every distribution. CocoaPods shipped `sandbox-pod` in 2013, a wrapper that ran the whole pod install under `sandbox-exec`. The generated profile still contains `(allow network-outbound)` with a “TODO make this stricter if possible” comment, the revisit issue was closed by a stale bot in 2017, and the binary, shipped thirteen years before the current proposals and long abandoned, is still listed in the gemspec. Deno is the only JavaScript package installer with any confinement, and its deny-by-default permission model is enforced in-process by the runtime rather than by the OS, with FFI as a documented way around it and a steady stream of permission-bypass advisories. The maintainers concede in their own hardening issue that an approved npm lifecycle script currently “executes with essentially full host access”, because the `node` shim inside it spawns `deno run -A`. ## Allowlists The run of supply chain attacks from nx through Shai-Hulud 2.0 produced a lot of shipped security work in JavaScript, all of it controlling which code runs rather than confining it. Every major client now blocks dependency lifecycle scripts by default behind an allowlist: pnpm led in January 2025, Bun had gated scripts since 2023, Yarn flipped the default in April 2026, and npm 12 followed in July. Cooldowns on newly published versions went from a proposal to on-by-default at pnpm, Yarn, and Deno within about a year, with most other ecosystems shipping opt-in equivalents. An RFC titled “Make npm install scripts opt-in” was opened in November 2021, collected around 369 thumbs-up, and stayed open for four and a half years before being closed in favour of the 2026 RFC that npm 12 implements. GitHub’s immediate response to Shai-Hulud was entirely credential and publishing hardening; the default flip on scripts came eight months after the worm and five years after the original RFC. I surveyed the allowlist mechanisms in June; an allowlist controls which packages get to run code, while a sandbox limits what that code can reach once it runs. The pnpm sandbox issue makes the case for the second axis directly: an allowlist is binary, and most packages with build scripts need to compile something in their own directory, which is a permission you can grant while withholding your SSH keys and the network; approving `esbuild`’s postinstall today extends that trust to every future version of it. ## Proposals The open proposals all date from the last fourteen months and specify the same primitives. Beyond pnpm’s and Deno’s, RubyGems has a December proposal to split `bundle install` into a download phase in which only Bundler’s own code runs, and an install phase that could run sandboxed with credentials stripped, and it has a maintainer in support: “I think this makes sense.” Spack’s April issue proposes Landlock and Seatbelt applied in-process between fetch and build, on a tracker whose original sandbox request from 2017 opened with “I could easily sneak a `rm -rf ~` into a package.” Arch has a draft merge request giving install scriptlets a private network namespace, which CachyOS already ships. Cargo’s sandbox issue has been open since 2018. The intervening years produced watt, Cackle, a pre-RFC from dtolnay written after serde_derive briefly shipped a precompiled binary, and an official 2024 project goal that ended with a specific negative result: WASI lacks process spawning, and build scripts exist to spawn `pkg-config`, C compilers, and `git`, so the WebAssembly approach fails. Then in August 2026 the arrayref attack delivered a typosquatted proc-macro dependency whose `build.rs` downloaded and ran a remote binary, with infrastructure Wiz links to DPRK campaigns. The issue filed in response was closed the same day as a duplicate of the 2024 allowlist thread. Zig’s proposal, from Andrew Kelley himself, is the most radical design on any tracker, compiling every `build.zig` to WebAssembly so it can only emit a build graph as data, on top of a fetch step that is already inert, and it has been open since January 2023. pip’s “Sandbox the running of setup.py” was opened in 2017 by a PyPA maintainer and cites Homebrew’s `sandbox.rb` as the model to copy. It is still open, along with a 2022 privilege-drop issue and a 2026 AppArmor one. Poetry’s maintainers gave the flattest refusal in the survey: a post-xz request for Landlock or seccomp self-sandboxing was closed as out of scope on portability grounds. uv’s threat model places the local machine inside the trust boundary and leaves confinement out of scope, and its maintainers decline on principle to add install hooks in the first place. The only Python-adjacent tool with a sandbox on its public roadmap is pixi, which already ships conda link scripts disabled by default behind a setting whose opt-in value is spelled `insecure`. Gradle’s sandbox mode issue has been open since 2019, Maven’s security page states that “the Maven security model assumes you trust the pom.xml” and isolation is your job, and JEP 486 permanently disabled the Security Manager in JDK 24, which removed the platform’s in-process sandbox primitive in the same year demand for one returned. NuGet’s 2020 issue about warning on code execution in MSBuild target files got a maintainer reply that removing it “will break many packages”, and was revived this July citing Shai-Hulud, with a commenter pointing at Yarn as the existence proof that fail-closed defaults are survivable. The C++ managers are absent from every category above: Conan recipes and vcpkg portfiles run arbitrary Python and CMake at install time, and I found no sandbox proposal on either tracker. ## Removal A second strategy has a better shipping record than sandboxing: removing the code execution entirely. Go and Elm omitted install hooks from the start. NuGet deleted `install.ps1` with PackageReference in 2017, though MSBuild targets from packages still execute at build time, which real malware has used. Composer runs only the root project’s scripts and put plugins behind an allowlist in 2021. Julia’s Artifacts system replaced most `build.jl` usage with declarative content-addressed downloads. CPAN’s practical mitigation is `x_static_install`, which skips executing `Makefile.PL` for pure-Perl distributions. Cabal’s Hooks build type narrows arbitrary `Setup.hs` replacement to named hook points. The distributions are doing the same for scriptlets, with Fedora replacing useradd scripts with declarative sysusers.d metadata and Arch surveying scriptlet usage with declarative hooks as the goal. Homebrew’s `*_steps` migration combines removal with confinement: the hook becomes signed data, and the remaining executable steps run inside the sandbox. Dart is the counterexample: pub’s install step historically consisted of placing files on disk. The native-assets build hooks stabilised this year add execution to that path, deferred to build time, in an environment the docs describe as semi-hermetic, with reproducibility as the sole stated goal. ## Primitives 2026’s proposals name the same primitives because few exist. On Linux, Landlock is in default kernels across the major distributions, runs unprivileged without a daemon or container runtime, and versions its ABI so a client can apply whatever protections the running kernel offers, which is the compatibility posture a package manager needs. Homebrew, pacman, and mise ship it. opam and Spack have open proposals to adopt it, and every agent vendor’s Linux sandbox is built on Landlock, namespaces, or both. On macOS, Homebrew, Claude Code, and Chrome all run on Seatbelt, which Apple deprecated in 2016 and has neither removed nor replaced, a situation developers have formally asked Apple to resolve. Windows lacks a directly comparable primitive, which is why Codex built a custom sandbox from restricted tokens, Cursor and Claude Code confine through WSL2, and the pnpm proposal may add Windows support only later. The agent problem and the package manager problem meet in CI, where a GitHub-hosted Actions job gets a virtual machine of its own and isolation ends at that boundary: every `uses:` step (itself a package install) and every package manager invoked inside the job shares the runner’s filesystem, environment, and secrets. The VM protects GitHub’s infrastructure, and everything the job values, secrets included, is inside it, so an install script runs with the same reach as the workflow that invoked it. Self-hosted runners are frequently persistent and shared, which removes even the per-job boundary. The shipped control is an allowlist over which actions may run, and confinement exists as Harden-Runner, a third-party agent that monitors and filters runner egress. CI is also where kernel sandboxes compose worst: inside a `container:` job, bubblewrap fails for want of privileged namespaces (opam has had the issue open since 2020), which is why Homebrew switched to Landlock and why Spack’s proposal applies restrictions in-process. The nx compromise started this way, with a workflow injection leaking the npm token that published the malicious versions. The open boundary is the one I keep coming back to from the threat model work: the hand-off. A sandboxed build that writes an install manifest, a cache entry, or a step list which the package manager then acts on with full privileges has moved the trust decision to whatever validates that output, and Homebrew’s LaunchServices escape was a hand-off bug. The removal strategy is one answer: a signed step list or a build graph emitted as data has a schema, and the package manager interprets it instead of executing it. The proposals now open at pnpm, RubyGems, Deno, and Spack still have to specify what validates a sandboxed build’s output.
112 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 24/09/2026
Making plans for the @fosdem 2027 package manager dev room 📦️
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 22/09/2026
I fucked up the publish dates, so two blog posts live today: nesbitt.io/2026/09/22/package-manag… nesbitt.io/2026/09/22/unfinished-wo…
nesbitt.io
Package Manager Threat Model, Revisited
I’ve spent a fair chunk of the last four months pointing the package manager CWE list and the threat model questions at real package managers, in some cases with help. Ten targets, mostly clients, a couple of registries, a mix of tools I’d used and tools I’d only read about. I also re-ran the advisory search that produced the original CWE list, filtered to everything published since May, to see what everyone else had been finding in the same window. The two lists have now been merged into a maintained page at /package-manager-threat-model/. ## Advisories 126 advisories against 23 package managers and registries between May and mid-September. About a quarter of everything ever filed against the same set of tools, which is mostly explained by three coordinated audits (one of pnpm producing twenty advisories over June and July, one of Homebrew, which I help maintain, producing thirteen, one of Flatpak producing ten in a single day) plus the OCI-registry implementations working through the same authorisation and DoS bugs the self-hosted language registries had five years earlier. Path traversal is still the top of the table by a distance, 33 advisories, and almost all of them come from manifest fields rather than archive entries: a package `name`, a `version`, a `bin` field, an entry-point script name, a lockfile alias, a patch target, a hash used as a directory. The May post had a paragraph noting the pattern extended beyond the archive; that paragraph now covers most of the category, so on the page the field-as-path case is the primary framing and the archive entry is the historical example. Four Python installers (uv, pip, pdm, conda) had the same entry-point-name traversal filed against them within five weeks of each other, and Composer had a `bin` field traversal fixed on July 20 and the fix bypassed on August 27. Argument injection got its predicted recurrence in a new VCS driver: Composer’s Perforce backend, matching the May post’s line about the git-driver fix leaving the p4 driver open almost exactly. The `--end-of-options` survey belongs here too. The pattern that recurred enough to name is credential leakage via a server-controlled response header. Nine advisories share one mechanism: the client asks registry A, registry A returns a `Location`, `Link`, or `WWW-Authenticate` realm pointing at host B, the client follows and sends credentials to B. ORAS had three, Renovate had four (one per registry type it pages through), Cargo and Homebrew one each. The May CWE-522 entry had the redirect case; the Link and realm variants are the same idea applied to headers a browser would ignore and a registry client parses. Five headings had zero entries in the window (unsafe deserialisation, terminal escapes, registry XSS, manifest confusion, weak crypto parameters), which says those categories were quiet rather than that they’re fixed. ## Audits A pattern scanner has rules for tainted-string-reaches-eval and unescaped-param-reaches-view; the rule it lacks is “which code paths grant ownership of a package name, and does any path’s precondition get satisfied by a different path’s output.” The design questions in the threat-model half are attacker-goal-shaped, and that turned out to be the gap a general-purpose scanner leaves: they ask what an attacker would want from a package manager specifically (a name, a publish credential, code on the machine that resolves dependencies) and then trace back to what confers it. Running Brakeman and CodeQL over the same repositories for calibration produced findings that were almost entirely disjoint from the audit’s. The CWE list catches mechanical clusters the design questions miss: four separate predictable-tempfile sites, six places a credential reaches a string that gets logged, five places package-controlled text reaches a terminal unstripped. Each is low severity; together they show the codebase lacks discipline around a class of operation, which is a useful thing to be able to say to maintainers with line numbers attached. Running both over the same code and letting them overlap was more useful than expected. When six independent framings (three CWEs, three design dimensions) all point at the same file, that convergence is a stronger signal than one rule firing, and it fell out of the structure for free. The write-up shows one finding with “also flagged under: …” and a maintainer reads that as six different attacker models flagging this line. Verifying each finding adversarially before reporting it, which in practice meant a second pass by an agent instructed to argue the finding was wrong, refuted about a fifth of raw findings with a specific reason: this looks like SSRF but the request goes through a filtering relay, this looks like unchecked deserialisation but `permitted_classes` is set three frames up. Those refutations turned out to be worth keeping, because each one documents an invariant the codebase relies on that is otherwise undocumented. The page now requires a negative-results list as an output for the same reason: a dimension with zero findings still records why, and an empty search establishes only that the search came back empty. A separate unverified-assumptions list holds the suspicions that trace to neither a finding nor an invariant, which gives an auditing agent somewhere to put uncertainty. The targets were a deliberate mix rather than a sample, so the counts describe those ten codebases rather than package managers in general. Across the ten: * Path traversal via a manifest field: eight * A command the user would expect to be read-only (`--list-steps`, `env`, `serve`, editor open, `--dry-run`) that runs dependency code: five * The tool’s own install script, release workflow, or bootstrap step downloading something without a hash check: six * Argument injection into git or an equivalent: four * Plain HTTP or an HTTPS-to-HTTP downgrade accepted silently: four * A lockfile or expiry field that’s recorded in the schema and ignored on install: three ## Additions Every audit that produced a useful write-up started by naming the trust boundary, who the tool places inside it and who outside, because that’s what sorts a finding into bug, accepted design, or non-issue. A build system that runs dependency code with full user privileges has, by design, put dependency authors inside the boundary; a finding of “dependency code runs unsandboxed” is then a design note, and the interesting findings are the ones that fire before that point. The page now asks for that statement first. The CDN and middleware layer was absent from both halves of the May checklist. GHSA-9j48-x3c3-mrp2 is a per-user API-key response cached by Fastly and served to the next requester, and the bug is in Rack middleware ordering plus CDN defaults rather than any controller line, which both the CWE list and the design questions would have missed because both read application code. The page has a CWE-524 entry for it now, and the audit prompt is: for every response carrying per-user data, what is between the app and the client, and what would make it cache. Mirrors and caching proxies get their own Part II heading. Most corporate clients resolve against an Artifactory, Nexus, or Verdaccio instance rather than the public registry, and the proxy shifts several answers at once: which source is authoritative for a name, whether a yank or a malicious-version flag upstream propagates through the cache, whether the proxy re-verifies checksums or serves whatever it cached first, whether the lockfile records the proxy URL or the origin, and how per-origin credential scoping handles a host that terminates one credential and holds a stronger one of its own. The questions were previously scattered under manifest confusion, integrity checks, and multi-source resolution. Feature composition produced the highest-severity findings across two audits, each of them two features whose trust assumptions differed at the seam: a grant of authority whose precondition one feature was designed to satisfy for the user’s own resources, satisfied instead by a different feature acting on someone else’s. It fits no CWE and there is no dangerous call to grep for. The page now has it as an explicit design question: for each grant of authority, list every code path that produces it and check the pairs. The sandbox hand-off is a related gap: a build that runs confined and then writes an install manifest, a step list, or a cache entry that the tool acts on with full privileges has moved the boundary to whatever validates that output. Several tools have a sandbox around the build while leaving what the build writes back unvalidated. The tool’s own release pipeline, split from its own dependencies, produced findings in six of ten audits (an unchecksummed install script, CI actions on floating tags in a job holding a publish credential, an unguarded `workflow_dispatch`, a bootstrap binary fetched unhashed during the build) and was a distinct enough surface from “what’s in the lockfile” to warrant its own heading. The heading also covers the client’s self-update path, `rustup self update` or `brew update` pulling the tool’s own source, and whether it meets the verification bar the tool sets for the packages it installs. Editor and language-server integration belongs under code-before-install: for several ecosystems the first thing that runs code on an untrusted checkout is the LSP the editor starts on folder open, before the user has typed a command. CWE-693 is broadened from build-sandbox escape to protection-mechanism bypass generally. Cooldowns, install-script allowlists, tap allowlists, and anti-downgrade checks all had bypasses filed in the window and they’re the same class of bug: a configurable protection with one code path that skips consulting it. CWE-326 covers weak parameters: a truncated hash, a 64-bit non-cryptographic hash used for integrity, a token from a non-cryptographic RNG, an iteration count set for 2010 hardware. The check runs and the parameter is small enough that it offers little protection. A few smaller adjustments: tagging every entry client / registry / both so an auditor knows which repo to read; adding filesystem normalisation (case-insensitive collisions, APFS Unicode) alongside registry name normalisation; noting under lockfile guarantees that verify-before-extract stops a network attacker while the pinned bytes can still be upstream-authored hostile input to the extractor; adding an audit-event-coverage prompt under maintainer lifecycle since “state change lacking a durable record” kept showing up. The May CWE post closed with a suggestion to subscribe to five or six other package managers’ advisory feeds because this month’s bug in someone else’s tar extractor is a decent description of the bug in yours. Four months of doing roughly that, plus running the list directly, has mostly confirmed it: the list of patterns is stable enough that new advisories slot into existing headings about nineteen times out of twenty, and the twentieth is what the additions above are for. The page now holds the maintained version; the two May posts stay as the dated snapshots.
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 22/09/2026
So strange, just ran into this problem: github.com/orgs/community/discussio… on a new repo that's never had any branch protection rules and secret scanning disabled. GitHub refused to let me publish v0.1.0 tag but v0.1.1 was fine. No reason given, blank branch protection page […]
mastodon.social
Original post on mastodon.social
100 0
Reposted by Andrew Nesbitt
Anil Madhavapeddy @avsm.amok.recoil.org.ap.brid.gy · 21/09/2026
Just added support for searching for info about threatened species near you to the Dash of Life! dashoflife.org/near-me
003 0
Reposted by Andrew Nesbitt
Ben Ramsey @ramsey.dev · 21/09/2026
Do I know anyone at PyPI or NPM who can help with an account issue?
004 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 20/09/2026
Put together another small go library, basically ruby-cff for parsing citation.cff files in go: github.com/git-pkgs/citation
github.com
GitHub - git-pkgs/citation: A dependency-free Go library for parsing CITATION.cff files and validating citation metadata
A dependency-free Go library for parsing CITATION.cff files and validating citation metadata - git-pkgs/citation
100 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 20/09/2026
Just shipped v0.1.0 of swhid-go for @swheritage with both conformance and performance improvements: github.com/andrew/swhid-go/releases…
github.com
Release v0.1.0 · andrew/swhid-go
Changelog 4ec6606 Add README and MIT license ef24c9d Add repository automation and signed releases 35b829d Bump github.com/cloudflare/circl from 1.6.1 to 1.6.3 5361cef Bump github.com/go-git/go-gi...
123 0
Reposted by Andrew Nesbitt
daniel r(ooooooh) 👻 @danielroe.dev · 19/09/2026
don't be nice.
roe.dev
Don't be nice
Sometimes, it's more important to be good than it is to be nice.
42740251 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 19/09/2026
This Week in Package Management: 19 September 2026 nesbitt.io/2026/09/19/this-week-in-…
nesbitt.io
This Week in Package Management: 19 September 2026
Week eighteen of the roundup, built from the package manager OPML feed collection and whatever I’ve posted or boosted on Mastodon. I added nineteen feeds to the OPML this week, mostly project blogs, plus GNU Guix, Zig and the Reproducible Builds monthly reports. ## Releases Homebrew 7.0.0 overlaps package preparation with downloads for faster installs, sandboxes formula and cask operations (home-directory reads are blocked by default), and adds `brew vulns`, backed by a new CC0-licensed OSV-format advisory database. It also ships BrewUI, a native macOS app for browsing and installing packages, drops macOS 10.15 support, and moves Intel Macs to Tier 3. Patch releases through 7.0.4 fix Perl bottle relocation under the shorter prefix and restrict which files are verified when tapping. Swift 6.4 makes Swift Build the default build system in SwiftPM and adds SBOM generation in SPDX and CycloneDX formats via SE-0509. pnpm 12.5 extends the Python support added in 12.4: each workspace project selects its own interpreter against `requires-python` (downloaded from python-build-standalone if missing), projects with a `[build-system]` install as editable, and a `shared-environment` setting resolves multiple members into one workspace-root `pylock.toml` and `.venv`. `pnpm add` now accepts Package URLs across the npm, cargo and pypi types. sbt 2.1.0-M1 moves the metabuild to Scala 3.9 and removes Apache Ivy as a dependency; plugins built for 2.1.x are incompatible with sbt 2.0.x. RubyGems and Bundler 4.0.21 normalises absolute symlink targets during gem extraction and rejects Bundler redirects that downgrade HTTPS to HTTP. Pixi 0.81.0 extends `pixi run --script` to fetch conda-script files from HTTP and HTTPS URLs, including Gists, reusing the cached environment. uv 0.12.16 verifies downloaded wheels and sdists against hashes supplied by the index; 0.12.17 adds a preview `minimum-libc-version` setting for the glibc and musl floor a universal resolution must satisfy, and rejects `pylock.toml` wheels whose filenames differ from their declared name or version. Renovate 44.103.2: the Dockerfile manager natively extracts pinned `apk add` and `apt install` packages from `RUN` instructions without a custom regex manager, and the GitHub Actions manager documents the 81 actions whose `with:` version inputs it updates. A new `minimumReleaseAgeBuffer` option covers sibling packages published after the main package. opam 2.6.0 is out. The shell hook now updates the opam-managed directory in place instead of prepending it to `PATH`, build directories are deleted sooner during install, and HTTP repository loads read `index.tar.gz` in memory to cut tens of thousands of syscalls to one on Windows and constrained filesystems. Also out: * mise 2026.9.11 * pipx 1.17.4 * PDM 2.29.2 * Hatch 1.18.1 * Hatchling 1.32.3 * MacPorts 2.12.6 * DNF5 5.4.5.0 * Deno 2.9.7 * sbt 2.0.9 * Pkg.jl 1.13.0 * cabal-install 3.18.2.0 * Docker Engine 29.8.1 * Gradle 9.8.0-RC2 * Gradle 9.9.0-M2 * Terraform 1.16.3 * OpenTofu 1.13.0-rc1 * Dependabot Core 0.396.0 ## Security The Rust security response WG warned of an ongoing social-engineering campaign against rust-lang team members and owners of popular crates: a video call is arranged under a job, project or contract pretext, then used to persuade the target to install a supposed audio codec or run a command placed on the clipboard, with the aim of publishing malware from the compromised account. Podman 6.1.2 and 5.8.7 fix CVE-2025-11395, where `podman load` on an image with a crafted layer tarball, or `podman volume import` on a volume with crafted symlinks, could overwrite files on the host. pnpm 12.4.2 stops a dependency’s executable from redirecting another package’s POSIX bin shim through its shell helpers (a reinstall replaces existing shims) and stops GitHub Actions homepage links from including server credentials. The Cygwin, MSYS2 and WSL shims still resolve `PATH` for Windows path conversion, so the redirect remains possible there. Aaron Patterson wrote up the mechanism behind the May rubygems.org spam campaign covered last week: a `--load ./script.rb` line in a gem’s `.yardopts` runs during YARD documentation generation, so publishing a gem executed arbitrary code inside rubydoc.info’s networked container, which the campaign used to extract cached rubygems.org API keys and publish more gems. ## Articles PyPI posted an incident summary for the intermittent 502 and 503 errors on file downloads through the second half of August: a Fastly canary deployment misconfiguration on one cache node combined with bugs in PyPI’s own Fastly config around fallback routing and range requests, all resolved by 28 August. An earlier post explains that PyPI changed its download counting on 24 August to log only distribution file downloads (`.whl`, `.tar.gz`, `.zip`) rather than every package-related request. About 39% of the previous totals were metadata fetches and are now excluded. ## Papers An Exploratory Study of Dependabot Cooldown Adoption in Open-Source GitHub Projects (Tanaka et al., arXiv) looks at repositories that enabled Dependabot’s cooldown feature: security was the stated motivation in 83 of the 92 adoptions that gave one, 97.2% set a general delay rather than per-update-type settings, and 64.3% of those set it to seven days. Python Import as an Execution Boundary (Chen and Li, arXiv) mines PyPI histories and advisories for bugs and vulnerabilities that trigger at `import` time: module-level and `__init__` code activates 98.3% of the cases they confirm, and 90% of the twenty initialisation-time advisory vulnerabilities are rated High or Critical. Fixes more often move when the import runs than remove the dependency. GANADI: Uncovering C/C++ OSS Reuse Genealogies (Kim et al., arXiv) clusters downstream C/C++ projects by pivotal functions to reconstruct which project copied code from which, then uses the resulting reuse tree to route vulnerability reports; 23 of 48 unpatched vulnerabilities they found this way were fixed after disclosure. CASHEWS: Source Preprocessor for LLM-based Malicious Package Detection (Noirot Ferrand et al., arXiv) deobfuscates, unbundles and backward-slices npm package source before it reaches an LLM scanner, raising analysis coverage from 69.1–85.7% to 98.8–100% across 512 large package files and cutting false negatives by up to 18.6 points. Freeriding and Rebellion: An Investigation of Open Source Vendor Relicensing and Member Hard Forking Events (Foster and Germonprez, Information Systems Journal) studies vendor relicensing events and the hard forks that follow: vendors invoke freeriding concerns to justify governance changes, and community members respond by realigning their engagement into forks. Dawn Foster has a summary post. ## Elsewhere The OpenJS Foundation CNA is pausing CVE triage, validation and assignment from 17 September to 6 October, citing the volume of AI-generated security reports reaching its volunteer team. Incoming reports queue for processing after the break; actively exploited issues still get a response through the OpenJS Slack. Pillow updated its security policy along the lines of CPython’s, asking reporters to verify LLM-generated findings, deduplicate batches, and check the project’s threat model before submitting; Hugo van Kemenade noted the previous day’s 82 reports totalled over 226,000 words. Emma Irwin has moved Open Source Wishlist to a standalone teaching tool that uses Ecosyste.ms metadata to surface single-maintainer risk and open vulnerabilities for a chosen project and generate a support plan. Irwin argues that the data, standards and expertise for open source sustainability already exist and funding is the missing piece. The PSF announced the results of the inaugural Python Packaging Council election covered last week: Brett Cannon and Pradyun Gedam take two-year seats, and Donald Stufft, Henry Schreiner and Ralf Gommers take one-year seats, on 541 ballots. The Reproducible Builds August report covers Brett Cannon’s write-up of what a low-friction reproducible-builds path on PyPI would need, `daleq4py` for establishing equivalence between rebuilt Python wheels, and the AROMA+ study of build reproducibility feasibility across Maven Central. A separate interview with Jochen Sprickerhof covers `reproduce.debian.net` reaching over 98% reproducibility for Debian packages, up from 33% in 2024, and the May policy change blocking non-reproducible packages from entering new Debian releases. Git 2.56.0-rc1 was tagged. ## git-pkgs I tagged nine repos this week: * tiers v0.1.1 (new), which layers a set of local package checkouts by their in-set dependencies to compute a release order, and iterates over that order to bump each package’s in-set dependencies through `managers` * history v0.1.0 (new), a pure-Go library for walking commits, file changes, trees and blobs in a Git repository, reading loose and packed objects through go-git * managers v0.12.0 * magic v0.4.0 * manifests v0.12.2 * registries v0.9.2 * archives v0.7.1 * gitignore v1.3.0 * vers v0.7.1 Send links for next week to @[email protected].
000 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 18/09/2026
Sometimes I think I’ve got the residential scrapers on @ecosystems under control, then wake up to an extra 4m unique ip addresses then next morning 😬
000 0
Reposted by Andrew Nesbitt
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 17/09/2026
Good Morning, Your Toaster Is Compromised nesbitt.io/2026/09/17/good-morning-…
nesbitt.io
Good Morning, Your Toaster Is Compromised
_The following is a transcript of the 7am hour of Rise & Grind, a nationally syndicated breakfast news programme, first broadcast Thursday 17 September 2026. Transcription by OpenClaw-4.2. Portions of this segment were pre-blurred at the request of the network._ **CHIP:** Good morning, good morning, welcome back to Rise & Grind, I’m Chip Halloran. **BRIE:** And I’m Brie Kensington. Chip, we have to start with the story that has been, and I’m sorry, _burning up_ our inbox all morning. **CHIP:** [laughs] She’s been holding that one since four a.m., folks. But it is a serious story. If you own a smart toaster, a connected espresso machine, certain models of pet feeder, you may have woken up on Tuesday to find those devices producing images that we are, frankly, not able to show you before the watershed. **BRIE:** We’re going to put some of those on screen now, heavily blurred. What you’re looking at there is a slice of sourdough from a viewer in Nebraska, and burned into that slice is a cartoon fox, wearing sunglasses, in what our legal team have asked me to describe only as “a pose.” **CHIP:** The same image, or variations of it, has appeared in latte foam, on the little screens on the front of smart fridges, and in at least one case spelled out in kibble by an automatic pet feeder. One school district in Ohio has pulled its entire cafeteria line. Three manufacturers have issued recalls. And nobody, Brie, seems to be able to tell us who did this or why. **BRIE:** Which is why we’ve brought in an expert. Joining us now from her home is Karen Oyelaran, she is an open source security advocate, **KAREN:** Researcher. **BRIE:** Researcher, thank you Karen, and Karen, I understand you’ve actually been tracking this particular hack for some time? **KAREN:** So it’s not really one hack, it’s the same underlying library being compromised for the third time in about two years. The component is called vulpine-lz4, it’s a compression library written in Rust, twelve stars on GitHub, and it ends up in appliance firmware because a build tool called snekpack vendors it, and most of these manufacturers use snekpack in their over-the-air update pipeline. The original library stopped getting releases when the maintainer left, so snekpack switched to a community fork called foxhole-lz4, and on Tuesday that fork pushed a release with a modified decompression routine. Instead of unpacking the manufacturer’s splash-screen assets it unpacks a hardcoded image buffer, which is the fox. It’s actually the library’s own mascot. Someone has just drawn it in a way the maintainer definitely didn’t. **CHIP:** OK so, a lot to unpack there, if you’ll pardon the **BRIE:** [laughs] **CHIP:** But let me make sure I’ve got the headline. Vulpine. Is that an individual, is that a group? Where are they based? **KAREN:** No, sorry, vulpine just means fox-like. It’s the name of the software. The person who wrote it isn’t the attacker, he’s actually the first victim in a sense, his package keeps getting **BRIE:** So there IS a he. There’s a person behind Vulpine. **KAREN:** There’s a person who wrote it, yes. Years ago. He’s not involved in this. **CHIP:** And who does he work for? Which of the appliance companies? **KAREN:** None of them. He wrote it on his own time and published it for free, and then the appliance companies, and honestly thousands of other companies, built it into their products. That’s just how modern software gets made, you pull in hundreds of these small components and most of them are maintained by one or two volunteers. **BRIE:** For free. **KAREN:** Yes. **BRIE:** Free like a trial, or, **KAREN:** Free like nobody pays him anything. There’s a donate button. I think it’s had about forty dollars through it. **CHIP:** Forty dollars total? For software that’s in, you said millions of appliances? **KAREN:** Somewhere north of thirty million devices, based on the firmware strings. And that’s just the appliances. It’s also a transitive dependency of cargo, which is the tool that builds most Rust software, so realistically it’s on almost every developer machine in the world as well. This is actually the point I’d really like to get across if I can, because the manufacturers shipping these toasters are **CHIP:** And I do want to come back to that Karen, but I think what viewers at home want to know first is, this individual, the Vulpine developer. Where is he now? Have authorities been in contact? **KAREN:** He won the EuroMillions in 2024 and moved to Portugal to farm goats. He hasn’t committed to the repository in about two years. Which, again, he’s allowed to do, it’s a hobby project, nobody was paying him to **BRIE:** I’m sorry, he _walked away_? From thirty million devices? **KAREN:** He didn’t walk away from thirty million devices, there weren’t thirty million devices when he wrote it. He wrote a compression library, put it online, and other people put it in toasters. He wasn’t consulted about the toasters. **CHIP:** Our producers did actually reach out to him overnight, and Brie, I believe we have his statement? **BRIE:** We do. I’ll read it in full. “Thank you so much for reaching out. I hear your concerns and I’m committed to doing better, both as a maintainer and as a model. In the meantime, please find below my recipe for a soft-rind chèvre. Warmest regards.” And then there is, in fact, a recipe. **CHIP:** So he IS engaging. That’s encouraging, at least. **KAREN:** No, that’s not him, that’s an AI auto-responder. He won’t have seen your email, everyone who writes to that address gets the recipe. **BRIE:** The recipe looks quite good, actually. **KAREN:** It is, I’ve made it. Look, can I just, the reason this keeps happening to this specific library is that it’s underneath billions of dollars of hardware and nobody funds it. There was CVE-2024-YIKES, same package. There was another one in June, CVE-2026-LGTM, same package again, that time it was AI security scanners approving it because the malware asked them nicely. After that one there was a working group set up specifically to look at **CHIP:** So there IS a working group. That’s reassuring. **KAREN:** It’s never met. It was scheduled into the same slot as the retrospective for the previous incident, which also never met. **CHIP:** But it exists. **KAREN:** A calendar invite exists. **BRIE:** Karen, I want to bring it back to the images for a second because I think that’s what’s alarming people. We’ve had the network’s standards team look at these and they’ve confirmed that the fox is, and I’m quoting the memo, “depicted as over eighteen and the sunglasses remain on throughout,” so we are able to discuss it. But who _drew_ this? Is this the same person who broke into the software? **KAREN:** So the artwork actually predates this attack. It first showed up embedded in the June incident as a decoy, the idea being that automated scanners would hit the image, refuse to describe it, and never reach the actual malware forty lines further down. Which worked, incidentally. This time someone’s just taken that same asset and pointed it at the toast. Honestly the artwork is the least interesting part, the interesting part is that a fork with eleven downloads can push a release on a Tuesday and be on your kitchen counter by Thursday because none of the vendors in between are checking, and none of them are checking because none of them think of this as _their_ code, because they didn’t pay for it, because nobody **CHIP:** And the eleven, sorry, you said eleven downloads, earlier you said something about twelve stars, help me out here. Twelve out of what? **KAREN:** It’s not out of anything, it’s just twelve people clicked a button that says star. **CHIP:** So it’s not a rating. **KAREN:** It’s more like a bookmark. **CHIP:** Twelve bookmarks. And that’s holding up thirty million toasters. **KAREN:** _Yes._ That is exactly the problem. And the companies selling those thirty million toasters, we’re talking about firms with nine and ten figure revenues, have collectively contributed zero engineering time and about forty dollars to the component they’re all standing on. If even one of them had funded a part-time maintainer, or an audit, or just read the **BRIE:** So who’s _liable_ , Karen? If I’m a viewer and my four-year-old has seen this fox on her breakfast, who do I call? **KAREN:** I mean, you’d call the manufacturer, they sold you the toaster. But they’ll point at the firmware vendor, and the firmware vendor will point at snekpack, and snekpack will point at a repository whose owner is currently milking a goat. There isn’t a throat to choke here, that’s what I’m trying to **CHIP:** But surely someone _owns_ open source. There’s a company behind Linux, isn’t there? **KAREN:** There’s a foundation. Several foundations. None of them own vulpine-lz4, it’s one person’s repo. Was one person’s repo. **CHIP:** And he’s just allowed to leave it there? Unlocked? For anyone to put foxes in? **KAREN:** He put a licence on it that says anyone can use it for anything and he’s not responsible for what happens. Every one of those manufacturers agreed to that licence when they pulled it in. They just didn’t read it, because again, they weren’t paying for it, so nobody thought of it as procurement, so nobody **BRIE:** I have to say, Chip, the more I hear about this the more it sounds like these open sources are a bit of a wild west. **CHIP:** It really does. Karen, last question because we’re up against the break. Practically speaking. Should people be unplugging their toasters this morning? **KAREN:** The manufacturers have all pulled the update, so anything that’s rebooted since yesterday is fine. And I’d just point out that the _toast_ was never dangerous. It’s bread. The dangerous version of this attack is the one you don’t see, where instead of drawing a fox it just reads your wifi credentials, and that version has almost certainly already happened to the same devices via the same library and nobody booked a segment about it because there wasn’t a picture. That’s really what I’d like people to take away, the fox is **CHIP:** So the toast is safe to eat. **KAREN:** The toast was always safe to eat. **CHIP:** There you go. Toast is safe, reboot your appliances, and I’m sure the authorities will get this Vulpine character sorted out. Karen Overland, open source advocate, thank you so much for joining us. **KAREN:** It’s Oyelaran, and it’s, no, that’s fine. Thank you for having me. **BRIE:** Fascinating stuff. When we come back: he’s fluffy, he’s fearless, and his owners say he simply cannot be contained. Kubernetes the golden retriever is scaling new heights this morning after landing his very first skateboarding sponsorship. That’s next on Rise & Grind. Don’t go anywhere. _[BREAK]_
1111 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 17/09/2026
Good Morning, Your Toaster Is Compromised nesbitt.io/2026/09/17/good-morning-…
nesbitt.io
Good Morning, Your Toaster Is Compromised
_The following is a transcript of the 7am hour of Rise & Grind, a nationally syndicated breakfast news programme, first broadcast Thursday 17 September 2026. Transcription by OpenClaw-4.2. Portions of this segment were pre-blurred at the request of the network._ **CHIP:** Good morning, good morning, welcome back to Rise & Grind, I’m Chip Halloran. **BRIE:** And I’m Brie Kensington. Chip, we have to start with the story that has been, and I’m sorry, _burning up_ our inbox all morning. **CHIP:** [laughs] She’s been holding that one since four a.m., folks. But it is a serious story. If you own a smart toaster, a connected espresso machine, certain models of pet feeder, you may have woken up on Tuesday to find those devices producing images that we are, frankly, not able to show you before the watershed. **BRIE:** We’re going to put some of those on screen now, heavily blurred. What you’re looking at there is a slice of sourdough from a viewer in Nebraska, and burned into that slice is a cartoon fox, wearing sunglasses, in what our legal team have asked me to describe only as “a pose.” **CHIP:** The same image, or variations of it, has appeared in latte foam, on the little screens on the front of smart fridges, and in at least one case spelled out in kibble by an automatic pet feeder. One school district in Ohio has pulled its entire cafeteria line. Three manufacturers have issued recalls. And nobody, Brie, seems to be able to tell us who did this or why. **BRIE:** Which is why we’ve brought in an expert. Joining us now from her home is Karen Oyelaran, she is an open source security advocate, **KAREN:** Researcher. **BRIE:** Researcher, thank you Karen, and Karen, I understand you’ve actually been tracking this particular hack for some time? **KAREN:** So it’s not really one hack, it’s the same underlying library being compromised for the third time in about two years. The component is called vulpine-lz4, it’s a compression library written in Rust, twelve stars on GitHub, and it ends up in appliance firmware because a build tool called snekpack vendors it, and most of these manufacturers use snekpack in their over-the-air update pipeline. The original library stopped getting releases when the maintainer left, so snekpack switched to a community fork called foxhole-lz4, and on Tuesday that fork pushed a release with a modified decompression routine. Instead of unpacking the manufacturer’s splash-screen assets it unpacks a hardcoded image buffer, which is the fox. It’s actually the library’s own mascot. Someone has just drawn it in a way the maintainer definitely didn’t. **CHIP:** OK so, a lot to unpack there, if you’ll pardon the **BRIE:** [laughs] **CHIP:** But let me make sure I’ve got the headline. Vulpine. Is that an individual, is that a group? Where are they based? **KAREN:** No, sorry, vulpine just means fox-like. It’s the name of the software. The person who wrote it isn’t the attacker, he’s actually the first victim in a sense, his package keeps getting **BRIE:** So there IS a he. There’s a person behind Vulpine. **KAREN:** There’s a person who wrote it, yes. Years ago. He’s not involved in this. **CHIP:** And who does he work for? Which of the appliance companies? **KAREN:** None of them. He wrote it on his own time and published it for free, and then the appliance companies, and honestly thousands of other companies, built it into their products. That’s just how modern software gets made, you pull in hundreds of these small components and most of them are maintained by one or two volunteers. **BRIE:** For free. **KAREN:** Yes. **BRIE:** Free like a trial, or, **KAREN:** Free like nobody pays him anything. There’s a donate button. I think it’s had about forty dollars through it. **CHIP:** Forty dollars total? For software that’s in, you said millions of appliances? **KAREN:** Somewhere north of thirty million devices, based on the firmware strings. And that’s just the appliances. It’s also a transitive dependency of cargo, which is the tool that builds most Rust software, so realistically it’s on almost every developer machine in the world as well. This is actually the point I’d really like to get across if I can, because the manufacturers shipping these toasters are **CHIP:** And I do want to come back to that Karen, but I think what viewers at home want to know first is, this individual, the Vulpine developer. Where is he now? Have authorities been in contact? **KAREN:** He won the EuroMillions in 2024 and moved to Portugal to farm goats. He hasn’t committed to the repository in about two years. Which, again, he’s allowed to do, it’s a hobby project, nobody was paying him to **BRIE:** I’m sorry, he _walked away_? From thirty million devices? **KAREN:** He didn’t walk away from thirty million devices, there weren’t thirty million devices when he wrote it. He wrote a compression library, put it online, and other people put it in toasters. He wasn’t consulted about the toasters. **CHIP:** Our producers did actually reach out to him overnight, and Brie, I believe we have his statement? **BRIE:** We do. I’ll read it in full. “Thank you so much for reaching out. I hear your concerns and I’m committed to doing better, both as a maintainer and as a model. In the meantime, please find below my recipe for a soft-rind chèvre. Warmest regards.” And then there is, in fact, a recipe. **CHIP:** So he IS engaging. That’s encouraging, at least. **KAREN:** No, that’s not him, that’s an AI auto-responder. He won’t have seen your email, everyone who writes to that address gets the recipe. **BRIE:** The recipe looks quite good, actually. **KAREN:** It is, I’ve made it. Look, can I just, the reason this keeps happening to this specific library is that it’s underneath billions of dollars of hardware and nobody funds it. There was CVE-2024-YIKES, same package. There was another one in June, CVE-2026-LGTM, same package again, that time it was AI security scanners approving it because the malware asked them nicely. After that one there was a working group set up specifically to look at **CHIP:** So there IS a working group. That’s reassuring. **KAREN:** It’s never met. It was scheduled into the same slot as the retrospective for the previous incident, which also never met. **CHIP:** But it exists. **KAREN:** A calendar invite exists. **BRIE:** Karen, I want to bring it back to the images for a second because I think that’s what’s alarming people. We’ve had the network’s standards team look at these and they’ve confirmed that the fox is, and I’m quoting the memo, “depicted as over eighteen and the sunglasses remain on throughout,” so we are able to discuss it. But who _drew_ this? Is this the same person who broke into the software? **KAREN:** So the artwork actually predates this attack. It first showed up embedded in the June incident as a decoy, the idea being that automated scanners would hit the image, refuse to describe it, and never reach the actual malware forty lines further down. Which worked, incidentally. This time someone’s just taken that same asset and pointed it at the toast. Honestly the artwork is the least interesting part, the interesting part is that a fork with eleven downloads can push a release on a Tuesday and be on your kitchen counter by Thursday because none of the vendors in between are checking, and none of them are checking because none of them think of this as _their_ code, because they didn’t pay for it, because nobody **CHIP:** And the eleven, sorry, you said eleven downloads, earlier you said something about twelve stars, help me out here. Twelve out of what? **KAREN:** It’s not out of anything, it’s just twelve people clicked a button that says star. **CHIP:** So it’s not a rating. **KAREN:** It’s more like a bookmark. **CHIP:** Twelve bookmarks. And that’s holding up thirty million toasters. **KAREN:** _Yes._ That is exactly the problem. And the companies selling those thirty million toasters, we’re talking about firms with nine and ten figure revenues, have collectively contributed zero engineering time and about forty dollars to the component they’re all standing on. If even one of them had funded a part-time maintainer, or an audit, or just read the **BRIE:** So who’s _liable_ , Karen? If I’m a viewer and my four-year-old has seen this fox on her breakfast, who do I call? **KAREN:** I mean, you’d call the manufacturer, they sold you the toaster. But they’ll point at the firmware vendor, and the firmware vendor will point at snekpack, and snekpack will point at a repository whose owner is currently milking a goat. There isn’t a throat to choke here, that’s what I’m trying to **CHIP:** But surely someone _owns_ open source. There’s a company behind Linux, isn’t there? **KAREN:** There’s a foundation. Several foundations. None of them own vulpine-lz4, it’s one person’s repo. Was one person’s repo. **CHIP:** And he’s just allowed to leave it there? Unlocked? For anyone to put foxes in? **KAREN:** He put a licence on it that says anyone can use it for anything and he’s not responsible for what happens. Every one of those manufacturers agreed to that licence when they pulled it in. They just didn’t read it, because again, they weren’t paying for it, so nobody thought of it as procurement, so nobody **BRIE:** I have to say, Chip, the more I hear about this the more it sounds like these open sources are a bit of a wild west. **CHIP:** It really does. Karen, last question because we’re up against the break. Practically speaking. Should people be unplugging their toasters this morning? **KAREN:** The manufacturers have all pulled the update, so anything that’s rebooted since yesterday is fine. And I’d just point out that the _toast_ was never dangerous. It’s bread. The dangerous version of this attack is the one you don’t see, where instead of drawing a fox it just reads your wifi credentials, and that version has almost certainly already happened to the same devices via the same library and nobody booked a segment about it because there wasn’t a picture. That’s really what I’d like people to take away, the fox is **CHIP:** So the toast is safe to eat. **KAREN:** The toast was always safe to eat. **CHIP:** There you go. Toast is safe, reboot your appliances, and I’m sure the authorities will get this Vulpine character sorted out. Karen Overland, open source advocate, thank you so much for joining us. **KAREN:** It’s Oyelaran, and it’s, no, that’s fine. Thank you for having me. **BRIE:** Fascinating stuff. When we come back: he’s fluffy, he’s fearless, and his owners say he simply cannot be contained. Kubernetes the golden retriever is scaling new heights this morning after landing his very first skateboarding sponsorship. That’s next on Rise & Grind. Don’t go anywhere. _[BREAK]_
1111 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 15/09/2026
Shadowing the Standard Library nesbitt.io/2026/09/15/shadowing-the…
nesbitt.io
Shadowing the Standard Library
I was reading Johann Rehberger’s write-up of an attack on a coding agent last week. The payload is a file called `struct.py` inside a zip archive. The agent unpacks the archive, writes its own small Python decoder in the extracted directory, and runs it. The decoder does `import base64`, `base64` internally does `import struct`, and Python resolves that to the attacker’s file because the script’s directory is the first entry on `sys.path`. Module-level code runs on import. The poisoned module re-exports the real `_struct` API so decoding still produces valid output and execution continues, and the payload relaunches itself with `python3 -I` so the second interpreter starts with a clean module path. That `-I` is the tell that this is a well-understood Python behaviour. Putting an ambient directory on the module search path is a default most dynamic-language runtimes shipped with early on, and several have since removed it, so I went through the ones I could find to see where each ended up. The problem is specific to resolving module lookups at run time against filesystem locations, so languages that bind everything at build time are mostly absent. ## Removed Ruby dropped `.` from `$LOAD_PATH` in 1.9.2, released August 2010. The NEWS entry is one line, “$: no longer includes the current directory, use require_relative”. `require_relative` resolves against the calling file’s location, independent of the process working directory, so a script can load its own siblings while keeping the working directory off the search path for every other `require` in the process. There was no CVE and no escape-hatch environment variable; 1.9 was already a compatibility break from 1.8 and the load-path change went in alongside everything else. Perl removed `.` from the end of `@INC` in 5.26.0, released May 2017. That one did have a CVE, CVE-2016-1238, reported by cPanel: a script that changes directory to `/tmp` and then loads an optional module runs whatever a local user has left at `/tmp/Module.pm`. Perl had traditionally shipped with `.` on `@INC`, and taint mode (`perl -T`) had always stripped it, so the risk was documented long before the fix. 5.26 added `PERL_USE_UNSAFE_INC=1` to restore the old behaviour for the transition, and downstream distributions carried patches for years while CPAN modules that depended on `.` being present were fixed one at a time. ## Designed out Node’s `require` checks core module names first, before `node_modules` or anything else on disk, so `require('http')` returns the built-in even with an `http.js` in the caller’s directory. Loading a neighbouring file has always taken an explicit relative path, `require('./http')`. Node 14.18.0 added the `node:` prefix so `require('node:http')` bypasses the require cache as well, and some newer built-ins such as `node:test` are only reachable that way. That protection covers core modules only: `require('express')` searches upward from the caller’s directory through each `node_modules`, so a `node_modules/express` inside an extracted archive is resolved ahead of any installed copy. Java resolves classes at run time from a classpath, and the default classpath when neither `-cp` nor `CLASSPATH` is set is `.`, but the bootstrap class loader finds `java.*` before the application loader searches the classpath, so a `./java/lang/String.class` is unreachable for the same reason a local `http.js` is in Node. Deno dropped the ambient search path entirely: every import is a URL or a relative path, and a bare specifier outside the import map is an error. Julia’s default `LOAD_PATH` is `["@", "@v#.#", "@stdlib"]`, three symbolic entries that expand to the active project environment, the user’s versioned default environment, and the standard library. `@` resolves to whichever `Project.toml` is active, regardless of which directory the process is in, so a script run from an untrusted directory looks up imports in a manifest file. PowerShell’s `Import-Module` searches `$env:PSModulePath`, which defaults to the per-user, all-users and `$PSHOME` module directories only, and the shell applies the equivalent rule to executable lookup: running a script in the working directory requires an explicit `.\` prefix, so a bare name searches only `$env:PATH`. ## Still there PHP’s `.` is the first entry in the default `include_path`, so `include 'config.php'` picks up a `config.php` in the working directory ahead of one under the PEAR path. Lua’s default `package.path` ends with `./?.lua;./?/init.lua`, so `require "json"` falls through to `./json.lua` after the installed-path entries have all missed. Lua’s own standard libraries, `string`, `table`, `math` and the rest, are registered in `package.loaded` before `require` searches any path, so a `./string.lua` is unreachable and only third-party names are exposed. In both PHP and Lua, dropping the working-directory entry means overriding the full path string, via `php -d include_path=...` or the `LUA_PATH` environment variable. Python prepends the script’s directory as `sys.path[0]` when running a file, the working directory when running `-m`, and an empty string, meaning the working directory, when running `-c` or the REPL. Isolated mode, `-I`, added in 3.4, suppresses that entry along with user site-packages and all `PYTHON*` environment variables. 3.11 added a narrower switch, `-P` and `PYTHONSAFEPATH`, which drops only the `sys.path[0]` entry and leaves the rest of the environment alone. The tracker issue behind `-P`, bpo-13475, was opened in November 2011. Victor Stinner, who landed `-P`, has a draft PEP in his personal repo proposing to make safe-path the default and citing Perl 5.26 as precedent. Ruby could drop `.` because `require_relative` shipped in the same release and gave scripts another way to load their siblings. Python’s explicit relative imports only work inside a package, so a standalone `script.py` importing `helper.py` from the same directory depends on `sys.path[0]` being that directory, and running it under `-P` fails with `ModuleNotFoundError`. Perl, Ruby and Lua all put `.` last, after the standard-library and site directories, so a file in the working directory could only supply a name that was missing everywhere else, and CVE-2016-1238 accordingly needed a target script that loaded an optional module. Python and PHP put the ambient directory first. The standard library comes after it on the path, `struct.py` in the working directory is loaded in place of the real `struct`, and any standard-library module read from disk is exposed the same way. Modules compiled into the interpreter and, since 3.11, the frozen startup set (`os`, `abc`, `io`, `codecs` among them) are served by `BuiltinImporter` and `FrozenImporter` on `sys.meta_path` before `PathFinder` touches disk; `struct` is a plain `.py` wrapper around a C extension and goes to `PathFinder`. | Entry on default path | Position | Stdlib shadowable | Removed in | Safe-mode switch ---|---|---|---|---|--- Ruby | `.` in `$:` | last | no | 1.9.2 (2010) | Perl | `.` in `@INC` | last | no | 5.26 (2017) | (`PERL_USE_UNSAFE_INC` restores) Node.js | none | | no | | Java | `.` when `-cp` unset | | no | | any `-cp` replaces it Deno | none | | no | | Julia | none (project manifest) | | no | | Lua | `./?.lua` in `package.path` | last | no | | PHP | `.` in `include_path` | first | yes | | Python | script dir / cwd in `sys.path` | first | yes | | `-I` (3.4), `-P` / `PYTHONSAFEPATH` (3.11) ## Threat model The Perl 5.26 release notes describe the risk as a script loading an optional module “when its current directory is untrusted (such as `/tmp`)”, and the mitigation for the twenty years before that was procedural: system scripts `chdir` somewhere safe before loading anything optional, and users run tools only from directories they control, advice written for a person or a fixed-cwd daemon choosing where the interpreter runs. A coding agent that downloads an archive, extracts it, writes a helper next to the contents, and runs the helper is the `/tmp` case with a different label on the directory. The archive determined the directory contents, and the agent’s own script is what triggers the import. Python is also the language agents default to for generated helpers: the sandboxed runtime for both OpenAI’s Code Interpreter and Anthropic’s code execution tool, and the interpreter Claude Code, the target in the write-up, invokes for ad-hoc scripts. In Rehberger’s version the shadowed module forwards to the real one, so the decoder returns a correct result. It is the same class of default as the override flags a subprocess can set through its environment: tolerable while a person supplied the working directory or the flag, and an agent processing an archive supplies the working directory as a side effect of extracting it.
000 0
Reposted by Andrew Nesbitt
Emma Irwin @sunnydeveloper.mastodon.social.ap.brid.gy · 13/09/2026
I've moved Open Source Wishlist (oss-wishlist.com) to a stand alone teaching tool. It uses Ecosyste.ms metadata for critical OSS projects to help identify risk, intervention, and expertise required to mitigate that risk. It lives as evidence that - sustainability is an accountability and funding […]
mastodon.social
Original post on mastodon.social
035 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 12/09/2026
“I could not run Rails locally because this machine has neither Ruby/Bundler nor Docker.” If this is in the description of your pull request, it’s unlikely to get any time spent on it.
010 0
Andrew Nesbitt @andrewnez.mastodon.social.ap.brid.gy · 12/09/2026
This Week in Package Management: 5 September 2026 nesbitt.io/2026/09/05/this-week-in-…
nesbitt.io
This Week in Package Management: 5 September 2026
Week sixteen of the roundup, built from the package manager OPML feed collection and whatever I’ve posted or boosted on Mastodon. I added Terraform, OpenTofu, Elm and PSResourceGet release feeds to the OPML this week. ## Releases pnpm 12.1 adds the workspace task scheduler to the Rust CLI, dispatching each package as soon as its dependencies finish where the previous scheduler waited for a whole topological batch, and moves login credentials into structured global config. 12.3 makes the global command shims native executables on every platform and extends the trust-policy flags to `pnpm remove` and `pnpm update`. On the 11.x line, 11.25 backports the task scheduler and adds `--resume-from` for recursive runs. rustup 1.29.1 checks for toolchain updates in parallel during `rustup update` and installs multiple components concurrently in `rustup component add`. Conan 2.32.0 adds LoongArch64 host detection, Xcode 26.6 and gcc 16.2 support, and lets `XcodeToolchain` accept arbitrary xcconfig build settings. PDM 2.29.0 exports editable local dependencies with relative paths in requirements files, and restricts locked packages to the platform they were resolved for when appending targets with `pdm lock --platform`. zizmor 1.30, the GitHub Actions workflow auditor, adds a `self-repository` audit and expands pre-commit support. Renovate 44.59.0 adds a manager for Microsoft’s Agent Package Manager, and 44.60.0 lets security-update PRs be rate-limited and stops the Go proxy datasource caching transient errors, a long-standing cause of flapping Go update PRs. The Maven 3.8.x branch has reached end of life; the final state is archived under a tag and the branch removed. Also out: * Homebrew 6.0.22 * snapd 2.77.1 * RubyGems and Bundler 4.0.20 * Bun 1.4.2 * Verdaccio 6.10.2 * Go 1.27.1 and 1.26.8 * Rust 1.98.1 * uv 0.12.10 * pipx 1.17.2 * conda 26.7.2 * Pixi 0.79.0 * mise 2026.9.1 * Dependabot Core 0.394.0 * Docker Engine 29.8.0 * Terraform 1.16.1 * Helm 4.3.0-rc.1 and 3.22.0-rc.1 * opam 2.6.0-beta2 * CPAN-Meta 2.150015 ## Security Podman 6.1.1 fixes CVE-2026-17106, a path traversal where a crafted tar archive could write outside the extraction directory via malicious links. Poetry 2.4.2 fixes three issues: installing an artifact absent from the lockfile when the source omits its hash, a path traversal when downloading from a compromised URL, and a path traversal in sdist extraction on Python 3.10.0-3.10.12 and 3.11.0-3.11.4. Coder disclosed that an attacker gained access to its Cloudflare account and added their own IPs to the module registry pool, serving credential-stealing modules for about fourteen hours on 31 August. Fixed in 2.37.0 with backports to 2.36.4, 2.35.7 and 2.34.9. This is what artifact signing is for: the tampered modules came from the real domain over valid TLS, so only a signature check against a key held outside the Cloudflare account would have flagged them. ## Articles Boring Python: dependency management (James Bennett) is a revised edition of the 2022 post: it now recommends PEP 751 lock files over pinned requirements files, allows uv or PDM for local development while keeping pip-with-hashes for production installs, and adds a section on three-day dependency cooldowns. The Holy Grail of Nixpkgs Version Ranges (Farid Zakaria) adds version-range constraints to nixpkgs by pairing a 309,000-version index of historical nixpkgs revisions with the clingo Answer Set Programming solver, so a query like `python@>=3.10` resolves to a concrete set of revisions. Mixing revisions can produce glibc symbol mismatches, which the solver constrains against using binary compatibility metadata. Security scanning my own code with Scrutineer and local coding models (Anil Madhavapeddy): notes on running Scrutineer, the code-scanning workflow tool that I wrote, against his own repos with a local GLM 5.3 model in place of a hosted one. He argues the triage decisions maintainers make on findings should themselves be tracked and fed into later scans across an organisation. ## Papers The Software Supply Chain as a Market for Lemons: A Multivocal Review of Trust Signal Collapse (Paramitha et al., arXiv) reviews 252 web sources and 870 Reddit threads on how practitioners pick dependencies: the cheap signals they rely on (stars, download counts, contributor activity) are now cheaper to fake than to earn, and the authors recommend costly signals such as cryptographic attestation as mandatory defaults. A Multi-Month Study of Git Commit Signing (Shittu et al., arXiv): 22 CS students configured commit signing independently, used it across four coursework projects and a second device, then examined a repository seeded with anomalous commits; nearly all signed every commit but over a quarter missed the anomalies. AgOSS: A Dataset and Multi-Layer Characterization of Open-Source Agricultural Software (Dudhaiya et al., arXiv) applies OpenSSF Scorecard, governance metrics, SBOM dependency analysis and KEV matching to 66 agricultural OSS repositories and non-agricultural controls; the agricultural projects score lower on raw Scorecard results but the gap disappears once project size and maturity are accounted for. ## Elsewhere NYU Tandon has launched the NYU Software Supply Chain Security Operations Center, led by Justin Cappos, embedding master’s students in open source projects for year-long security placements; the first cohort of 8-10 starts January 2027 with support from Google and DTCC. Sovereign Tech Agency with Erik Möller (Josh Bressers, Open Source Security): an interview with the STA’s Director of Programs on the Sovereign Tech Fund, its maintainer fellowships, funding for standards-body participation, and the Sovereign Tech Resilience programme for security audits and post-quantum work. Introducing vulnbrocards.com (William Woodruff): the vulnerability-triage brocards from earlier posts now each have a stable URL. Determining Value and Viability Using CHAOSS Practitioner Guides (Dawn Foster) is part three of the series, covering the Demonstrating Organizational Value and Assessing Viability guides for justifying open source contribution work to leadership and evaluating dependency risk. Tracking Trends in Open Source AI Policy (Emma Irwin) applies the CHAOSS AI Alignment working group’s use-policy-specificity metric to 39 open source project AI policies: 25 address code contributions, none address environmental impact, infrastructure strain or notetaker bots. GitHub added a star history REST endpoint that returns timestamped aggregate star counts for a repository without listing the accounts that starred it. The Cargo team put out a call for testing for `-Zchecksum-freshness`, which detects the need to rebuild from file content checksums, replacing the mtime check. The plan is to stabilise it as `build.fingerprint = "content"` in `.cargo/config.toml`. CERN is migrating its 2,200 accelerator-control machines from RHEL to Debian 13 by the end of 2026. The announcement calls the `-march=x86-64-v2` compiler default forced obsolescence for older hardware and lists gaps in Debian’s standard tooling for automated package building and publishing. The recording of Is the InnerSource Commons Good for Open Source?, the FOSS Backstage 2026 talk Ben Nickolls and I gave analysing 800 InnerSource Commons member companies, is now up. FOSDEM 2027 will be held on 30-31 January. ## git-pkgs I tagged 23 repos this week: * git-pkgs v0.20.0 * archives v0.7.0 * artifacts v0.2.1 * brief v0.13.0 * capcheck v0.1.4 * changelog v0.2.1 * clone v0.7.3 * dependents v0.2.0 * distill v0.1.2 * enrichment v0.7.1 * forge v0.10.0 * licenses v0.7.0 * magic v0.3.1 * manifests v0.12.0 * outline v0.2.2 * pin v0.2.1 * provides v0.2.1 * proxy v0.8.1 * purl v0.1.20 * registries v0.9.1 * sigstore v0.2.1 * vers v0.7.0 * vulns v0.2.3 Send links for next week to @andrewnez@mastodon.social.
010 0