You probably ran a package install command today without thinking twice. Neither did the thousands of developers whose machines are now quietly compromised by North Korean state-sponsored hackers.
Here’s what nobody in the Go and PHP ecosystems wants to admit: the registries we trust to power our builds are running on an honor system, and the honor system has been breached.
The campaign is called PolinRider. North Korean threat actors have been systematically compromising legitimate packages in the Go and Packagist registries — not by breaking encryption, not by exploiting zero-days, but by walking through a door that was never locked. Because unlike NPM and PyPI, which now require multi-factor authentication and additional publishing credentials, Go and Packagist treat publishing like a suggestion box. Drop your code in. No extra verification. No second factor. No friction.
The hackers didn’t pick the lock. The registry operators left the key under the mat and called it ‘openness.’
Most coverage of this story frames it as a tale of clever adversaries and evolving tactics. That’s the wrong frame. The real story is about design choices — choices made by the people who run these registries, who decided that the friction of requiring MFA was worse than the risk of state-sponsored supply chain attacks. They effectively outsourced security to the community and hoped for the best.
Let’s be clear about what that means in practice. When you type go get or composer install, you’re placing implicit trust in a chain of maintainers, credentials, and infrastructure that — in the case of Go and PHP — has no enforced second layer of authentication. You’re betting your production environment, your CI/CD pipeline, and potentially your entire organization on the assumption that every package author’s account is secure. It isn’t.
NPM learned this lesson the hard way. After years of high-profile account takeovers and malicious package incidents, they implemented mandatory 2FA for publishers. PyPI followed a similar path. The Go and Packagist teams? They watched all of that happen and decided the trade-off wasn’t worth it.
Convenience is a feature until it becomes an attack surface. In package registries, it already has.
The tension here is fundamental, and it’s not going away. The same low-friction publishing model that makes open source vibrant — anyone can contribute, anyone can publish, anyone can improve — is exactly what makes it trivially weaponizable. You can’t require a background check for every package maintainer without killing the ecosystem’s soul. But you can require a second authentication factor. You can enforce publishing credentials. You can make it harder than ‘compromise one developer’s password and you’re in.’
The Go and Packagist operators have chosen not to. That’s not negligence by accident — it’s a deliberate calculation. They’ve weighed the community’s desire for frictionless contribution against the probability of state-sponsored infiltration and decided the latter is acceptable collateral damage. Your software supply chain is the collateral.
So what do you do while the registries catch up to where NPM was three years ago?
Stop trusting implicitly. Verify checksums. Use private mirrors for critical dependencies. Implement stricter dependency scanning that doesn’t just check for known CVEs but flags suspicious publish patterns, new maintainer additions, and unexpected version bumps. Treat every package update as a potential injection point, because in the current model, that’s exactly what it is.
The open source model was built on trust. The registries that serve it are quietly betting that trust against an adversary with unlimited patience and a state budget.
This isn’t a call to abandon Go or PHP. It’s a call to stop pretending the current publishing model is safe. NPM and PyPI got burned and adapted. Go and Packagist are standing in the same fire and calling it warmth.
The next time you run a package install, ask yourself: who verified this? If the answer is ‘nobody,’ you have your answer about whether you should trust it.
FAQ
Q: Isn't this just fearmongering? How many packages were actually compromised?
A: The PolinRider campaign has compromised legitimate, widely-used packages — not obscure projects. Even a single compromised dependency in your tree can pivot into full system access. The number matters less than the fact that the attack path requires no zero-day and no encryption break. It's a credential problem, and it's systemic.
Q: What should my team actually do about this today?
A: Three things: pin your dependencies with verified checksums, set up a private mirror for critical packages so you control what enters your build, and add dependency scanning that flags suspicious metadata changes (new maintainers, unexpected version jumps, publish timing anomalies). Don't wait for the registries to fix this.
Q: Isn't requiring MFA just going to kill community participation in Go and PHP?
A: NPM and PyPI both implemented mandatory 2FA and their ecosystems didn't collapse. The 'MFA kills participation' argument is a straw man pushed by people who don't want to deal with the friction. One extra tap on a phone is not the death of open source — state-sponsored supply chain attacks might be.