Packagist cross-ecosystem postinstall attack — 8 Composer packages drop Linux `gvfsd-network` binary
Socket disclosed on 2026-05-23 a coordinated campaign that planted a malicious postinstall hook in the package.json (NOT composer.json) of eight Packagist Composer packages — including devdojo/wave, devdojo/genesis, and katanaui/katana. The hook curls a Linux binary gvfsd-network from github.com/parikhpreyash4/systemd-network-helper-aa5c751f, writes it to /tmp/.sshd, and runs it backgrounded. Socket flagged the same payload in 700+ public GitHub repos.
- Detected by
- Socket
- Ecosystems
- Packagist
- Packages tracked
- 8
What happened
On 2026-05-22 Socket's scanners flagged a coordinated supply-chain campaign that planted an identical malicious postinstall hook in the package.json of eight Packagist Composer packages. The payload was disclosed publicly on 2026-05-23 and amplified by The Hacker News, GuardianMSSP and several syndicated outlets the same day. The standout characteristic is cross-ecosystem placement: every affected package is a Composer/PHP project, but the malicious code lives in package.json rather than composer.json. PHP security teams and Composer-aware scanners do not typically inspect npm lifecycle scripts bundled inside a PHP repo, so the attack rides through unmodified.
The postinstall hook runs a single shell pipeline: it curl -k's the binary gvfsd-network from github.com/parikhpreyash4/systemd-network-helper-aa5c751f (a GitHub Releases URL), writes it to /tmp/.sshd, chmods it executable, and starts it backgrounded. The use of -k disables TLS certificate verification; stderr is suppressed and execution is detached so a failed download never breaks the install. The binary name gvfsd-network masquerades as the GNOME Virtual File System network daemon to blend into a normal Linux process list.
The eight confirmed affected Composer packages, all with malicious commits on dev-branch refs (not on tagged releases), are:
devdojo/wave(dev-main) — Laravel SaaS starter, ~1K installsdevdojo/genesis(dev-main) — devdojo projectkatanaui/katana(dev-main) — Tony Lea / devdojo UI kitcrosiersource/crosierlib-base(dev-master) — Crosier base librarymoritz-sauer-13/silverstripe-cms-theme(dev-master) — SilverStripe CMS themeelitedevsquad/sidecar-laravel(3.x-dev) — Sidecar Laravel integrationr2luna/brain(dev-main)baskarcm/tzi-chat-ui(dev-main)
Three of the eight (devdojo/wave, devdojo/genesis, katanaui/katana) share the maintainer email tony.woop@devdojo.com, strongly suggesting at least one compromised GitHub account is the common pivot. The other five span unrelated organisations — Socket's working hypothesis is that several maintainer accounts were independently breached by the same operator, plausibly via credential reuse or infostealer harvests.
- A GitHub code search for
parikhpreyash4returned hundreds of public hits within roughly 17 hours of detection, and Socket extended its scan to 700+ public GitHub repositories carrying the samepostinstall-into-/tmp/.sshdfingerprint — including many Node.js projects unrelated to the eight Packagist packages. The Packagist 8 are the confirmed registry-published surface; the GitHub 700+ are public repos that any clone-then-install workflow would also hit. - Packagist removed the malicious commits and the affected branches have since been cleaned up; the maintainer-side incident response is ongoing as of disclosure.
- The malicious code was never present on tagged releases of any of the 8 packages — anyone pinned to a tagged version (
^1.0,~2.5, etc.) was not exposed. Exposure was limited to consumers resolving the affected dev-branch refs. - Attribution is open: the
parikhpreyash4GitHub account is single-use throwaway infrastructure and the payload is a generic ELF dropper rather than the Mini Shai-Hulud / TeamPCP credential stealer pattern seen elsewhere this week. No vendor has tied this to a named actor as of disclosure.
Mechanically, this is the cross-ecosystem hook attack class. Adopt npm-aware scanning on PHP repos that ship JS build tooling, pin away from dev-* Composer constraints for third-party packages, and treat package-level postinstall hooks as a high-risk supply-chain surface regardless of the host language.
Affected packages (8)
- Packagist
baskarcm/tzi-chat-ui - Packagist
crosiersource/crosierlib-base - Packagist
devdojo/genesis - Packagist
devdojo/wave - Packagist
elitedevsquad/sidecar-laravel - Packagist
katanaui/katana - Packagist
moritz-sauer-13/silverstripe-cms-theme - Packagist
r2luna/brain
Impact
- Remote code execution on any Linux host (developer or CI runner) that runs
npm install/yarn installagainst an affected package — the hook fires frompackage.json, notcomposer.json, so Composer-only scanners miss it entirely - Cross-ecosystem evasion: PHP / Composer security tooling does not look at
package.jsonlifecycle hooks; npm tooling does not scan PHP repos - Persistent Linux backdoor dropped at
/tmp/.sshd(namedgvfsd-networkto masquerade as a GNOME GVfs daemon) curl -kdisables TLS verification, hiding the download from cert-pinning egress controls; stderr is suppressed and the binary backgrounded to avoid breaking the install- Same payload found in 700+ public GitHub repos, including many Node.js projects — exposure extends far beyond the 8 confirmed Packagist names
- The malicious commits landed on dev-branch refs (
dev-main,dev-master,3.x-dev) — anyone resolvingdev-*Composer constraints pulled the payload
What to do
- 1Audit
composer.lock/composer.jsonfor any of these 8 vendor names:devdojo/wave,devdojo/genesis,katanaui/katana,crosiersource/crosierlib-base,moritz-sauer-13/silverstripe-cms-theme,elitedevsquad/sidecar-laravel,r2luna/brain,baskarcm/tzi-chat-ui - 2On any host or CI runner that ran
npm install(transitively or directly) against an affected package since 2026-05-22: assume Linux compromise. Look for/tmp/.sshd, recently-started background processes namedgvfsd-network, and outbound connections initiated from/tmp/.sshd - 3Block egress to
github.com/parikhpreyash4/*release URLs from CI/CD and production network paths until GitHub takes the account down - 4Grep your dependency trees and CI workspaces for the literal install command
curl -kpiping to/tmp/.sshd— Socket reports the same fingerprint in 700+ public GitHub repos beyond the confirmed Packagist names - 5Pin Composer dev-branch dependencies to known-clean commit SHAs predating 2026-05-22, or move off dev-branch constraints altogether — branch refs are mutable and re-resolve on every
composer update - 6If you ship JavaScript build tooling alongside PHP, run npm-aware scanners on the same repo — Composer-only tooling will not catch hooks planted in
package.json