Packagist GitHub Postinstall Hook Malware Campaign

A campaign inserted malicious package.json postinstall hooks into Packagist-linked GitHub repositories, causing npm install workflows to download and execute a GitHub Releases binary as /tmp/.sshd.

Date:
Severity:
high
Sources:
1
#supply-chain#packagist#github#npm#postinstall

Executive Summary

Socket reported a supply-chain campaign in which GitHub repositories behind Packagist packages contained a malicious package.json postinstall hook. Eight Packagist packages were confirmed, while broader GitHub search results showed hundreds of references to the same attacker-controlled payload pattern Socket.

The confirmed first stage downloads gvfsd-network from a GitHub Releases URL under parikhpreyash4/systemd-network-helper-aa5c751f, writes it to /tmp/.sshd, marks it executable, and launches it in the background. The second-stage binary was unavailable when Socket followed up, so defenders should treat execution as unknown malware with potential credential and persistence impact Socket.

Key Facts

threat_type: "malicious postinstall hook in Packagist-linked GitHub repositories"
ecosystem: "Composer/Packagist with npm lifecycle execution"
registry: "Packagist and GitHub"
affected_packages:
  - "moritz-sauer-13/silverstripe-cms-theme"
  - "crosiersource/crosierlib-base"
  - "devdojo/wave"
  - "devdojo/genesis"
  - "katanaui/katana"
  - "elitedevsquad/sidecar-laravel"
  - "r2luna/brain"
  - "baskarcm/tzi-chat-ui"
malicious_versions:
  - "dev-main"
  - "dev-master"
  - "3.x-dev"
known_good_versions: []
fixed_or_safe_versions:
  - "unknown; verify upstream repository cleanup before reinstalling branch-tracking versions"
execution_trigger: "npm install executing package.json scripts.postinstall"
primary_impact: "arbitrary binary download and execution on developer or CI systems"
campaign_context: "A PHP/Composer ecosystem compromise that uses Node/npm lifecycle scripts as the execution path."
confidence: "medium"
canonical_source: "https://socket.dev/blog/malicious-postinstall-hook-found-across-700-github-repos"
last_verified: "2026-05-24"

Source Confidence & Evidence Mapping

  • confirmed: Socket lists eight Packagist packages containing the malicious postinstall hook Socket.
  • confirmed: The hook downloads from parikhpreyash4/systemd-network-helper-aa5c751f GitHub Releases, writes /tmp/.sshd, sets executable permissions, and runs it in the background Socket.
  • confirmed: The second-stage binary was not available during Socket’s follow-up analysis, limiting behavioral certainty Socket.
  • likely: Additional GitHub repositories beyond the eight confirmed Packagist packages may have been seeded with the same hook, but each hit should be validated before being counted as a distinct compromise.
  • unclear: The final payload behavior, victim count, and cleanup status of every branch-tracking package remain open.

Attack Execution Flow

sequenceDiagram
    autonumber
    actor Attacker
    participant Repo as GitHub Repository
    participant Packagist as Packagist
    participant Build as Developer or CI Build
    participant Release as GitHub Releases

    Attacker->>Repo: Add package.json postinstall script
    Repo->>Packagist: Branch-tracking version reflects poisoned source
    Packagist->>Build: Dependency source is installed or built
    Build->>Build: npm install runs postinstall
    Build->>Release: Download gvfsd-network
    Build->>Build: Write and execute /tmp/.sshd

Timeline

  • 2026-05-22 Socket publishes the Packagist/GitHub postinstall campaign report Socket.
  • 2026-05-24 This local feed split creates a standalone article for the campaign rather than grouping it into a weekly roundup.

What Happened

The campaign abused a cross-ecosystem blind spot: PHP projects can contain JavaScript build assets and package.json files, and many developer or CI environments run npm install as part of frontend asset preparation. The affected packages were Packagist entries, but execution happened through npm lifecycle behavior inside the repository source tree.

Socket confirmed eight Packagist packages with the malicious hook and described a broader set of GitHub references matching the same pattern. The distinction matters: defenders should immediately handle the eight confirmed package names, then use the IoCs below to hunt for other repositories or forks that contain the same postinstall payload.

Technical Analysis

Initial Access

The public report does not prove a single initial access path. The observed state is source repositories containing a malicious package.json script and Packagist branch-tracking package versions reflecting those repository states Socket.

Package or Artifact Tampering

The tampering is a scripts.postinstall entry in package.json. The hook uses curl to fetch a file named gvfsd-network from GitHub Releases, writes it as /tmp/.sshd, sets execute permissions, and starts it in the background Socket.

Execution Trigger

The trigger is npm install. Composer alone may not execute the hook, but projects that install frontend dependencies or run build scripts can execute it during development, CI, packaging, or deployment.

Payload Behavior

Only the first stage is confirmed from public reporting. The second-stage binary was unavailable when Socket attempted retrieval, so defenders should not assume a narrow payload. Treat execution as arbitrary native-code compromise until endpoint and network telemetry prove otherwise.

Exfiltration / C2

The confirmed network dependency is the GitHub Releases URL hosting gvfsd-network. Any later C2 behavior is unknown from the reviewed public source.

Propagation

No autonomous propagation is confirmed. The practical spread mechanism is repository reuse: branch-tracking Packagist versions and forks can continue to reflect malicious source if maintainers do not clean the underlying repository state.

Obfuscation or Evasion

The campaign hides in ecosystem mismatch. A PHP dependency carrying a JavaScript lifecycle hook may be missed by Composer-focused scanners, and /tmp/.sshd resembles a system service name while living in a temporary path.

MITRE ATT&CK Mapping

TacticTechnique IDTechnique NameObserved Behavior
Initial AccessT1195.002Compromise Software Supply ChainPackagist-linked source repositories contained malicious install hooks.
ExecutionT1059.004Unix Shellpostinstall used shell commands to download and execute a binary.
Command and ControlT1105Ingress Tool TransferHook downloaded gvfsd-network from GitHub Releases.
Defense EvasionT1036MasqueradingPayload was written as /tmp/.sshd.

Affected Assets and Blast Radius

affected_assets:
  ecosystems:
    - "Packagist"
    - "Composer"
    - "npm"
  packages:
    - "moritz-sauer-13/silverstripe-cms-theme"
    - "crosiersource/crosierlib-base"
    - "devdojo/wave"
    - "devdojo/genesis"
    - "katanaui/katana"
    - "elitedevsquad/sidecar-laravel"
    - "r2luna/brain"
    - "baskarcm/tzi-chat-ui"
  versions:
    - "dev-main"
    - "dev-master"
    - "3.x-dev"
  repositories:
    - "parikhpreyash4/systemd-network-helper-aa5c751f"
  ci_cd_systems:
    - "GitHub Actions"
    - "Composer/npm build pipelines"
  container_images: []
  developer_tools:
    - "Composer"
    - "npm"
credentials_at_risk:
  - "unknown; treat all secrets reachable from affected developer or CI hosts as exposed if /tmp/.sshd executed"
not_currently_known_to_affect:
  - "Projects that used the affected Composer packages but never executed npm install or equivalent lifecycle scripts."

Indicators of Compromise

package_versions:
  - "moritz-sauer-13/silverstripe-cms-theme dev-master"
  - "crosiersource/crosierlib-base dev-master"
  - "devdojo/wave dev-main"
  - "devdojo/genesis dev-main"
  - "katanaui/katana dev-main"
  - "elitedevsquad/sidecar-laravel 3.x-dev"
  - "r2luna/brain dev-main"
  - "baskarcm/tzi-chat-ui dev-main"
files:
  - "package.json"
  - "/tmp/.sshd"
hashes: []
domains:
  - "github[.]com"
urls:
  - "hxxps://github[.]com/parikhpreyash4/systemd-network-helper-aa5c751f/releases/latest/download/gvfsd-network"
ips: []
process_patterns:
  - "curl -skL ... -o /tmp/.sshd"
  - "chmod +x /tmp/.sshd"
  - "/tmp/.sshd running in background"
network_patterns:
  - "download of gvfsd-network from parikhpreyash4/systemd-network-helper-aa5c751f"
provenance_signals:
  - "PHP/Composer package unexpectedly containing npm postinstall lifecycle script"

Detection and Hunting

lockfiles:
  - "Search composer.lock for the eight confirmed Packagist packages."
  - "Flag branch-tracking versions dev-main, dev-master, and 3.x-dev for manual review."
filesystem:
  - "Search source trees for parikhpreyash4, gvfsd-network, /tmp/.sshd, curl -skL, and scripts.postinstall."
process:
  - "Alert on npm lifecycle scripts writing executables under /tmp."
  - "Alert on /tmp/.sshd process execution."
network:
  - "Search proxy logs for the GitHub Releases gvfsd-network URL."
github_audit:
  - "Review source commits that introduced package.json postinstall hooks in PHP projects."
ci_cd:
  - "Review npm install runs for affected projects after the malicious commit entered the branch."
registry:
  - "Block or pin affected branch-tracking Packagist package versions until source cleanup is verified."
sigma_candidates:
  - "NPM Postinstall Downloads GitHub Release Binary To /tmp/.sshd"
yara_candidates:
  - "Unavailable until gvfsd-network sample is recovered."

Remediation Workflow

  • Immediate: Stop builds for affected projects, preserve CI logs and dependency caches, block the GitHub Releases payload URL, and isolate systems where /tmp/.sshd executed.
  • Short-term: Remove the malicious postinstall, pin Composer dependencies to clean commits, purge Composer/npm caches, and rotate secrets reachable by affected developer and CI hosts.
  • Long-term: Treat package lifecycle scripts in non-JavaScript projects as high-risk, require review for new package.json scripts, and prevent production builds from consuming branch-tracking dependency references without approval.

Defensive Lessons

  • prevent: Branch-tracking dependency versions and cross-ecosystem build hooks need the same review as normal package updates.
  • detect: Search source trees for lifecycle scripts, not only package registries for known malicious versions.
  • respond: Unknown second-stage binaries require broad credential rotation and endpoint triage, even when the first-stage script looks simple.

Open Questions

  • What did gvfsd-network do after execution?
  • Which GitHub references beyond Socket’s eight confirmed Packagist packages were true compromises?
  • Which affected package branches have been cleaned and protected?

Sources

  1. Socket: Malicious Postinstall Hook Found Across 700+ GitHub Repositories - Role: PRIMARY_RESEARCH - Impact: Documents confirmed packages, postinstall code behavior, payload URL, and cleanup caveats.

Machine-Readable Event Profile

{
  "schema_version": "2.0",
  "event_id": "packagist-github-postinstall-hook-campaign-2026-05-22",
  "event_name": "Packagist GitHub Postinstall Hook Malware Campaign",
  "publication_state": "publish_ready",
  "confidence": "medium",
  "attack_types": ["malicious postinstall", "source repository compromise", "arbitrary binary execution"],
  "sources": {
    "direct": [],
    "primary_research": ["https://socket.dev/blog/malicious-postinstall-hook-found-across-700-github-repos"],
    "correlated": []
  },
  "affected_assets": {
    "ecosystems": ["Packagist", "Composer", "npm"],
    "packages": ["moritz-sauer-13/silverstripe-cms-theme", "crosiersource/crosierlib-base", "devdojo/wave", "devdojo/genesis", "katanaui/katana", "elitedevsquad/sidecar-laravel", "r2luna/brain", "baskarcm/tzi-chat-ui"],
    "versions": ["dev-main", "dev-master", "3.x-dev"],
    "repositories": ["parikhpreyash4/systemd-network-helper-aa5c751f"],
    "ci_cd_systems": ["GitHub Actions", "Composer/npm build pipelines"],
    "container_images": [],
    "developer_tools": ["Composer", "npm"],
    "credentials_at_risk": ["unknown; all secrets reachable from hosts executing /tmp/.sshd"]
  },
  "timeline": {
    "first_seen": "unknown",
    "malicious_publish_time": "unknown",
    "discovery_time": "2026-05-22",
    "removal_time": "mixed",
    "disclosure_time": "2026-05-22",
    "patch_or_fix_time": "unknown"
  },
  "artifact_analysis": {
    "malicious_artifacts": ["package.json scripts.postinstall", "/tmp/.sshd", "gvfsd-network"],
    "execution_trigger": "npm install postinstall",
    "payload_behavior": ["download GitHub Releases binary", "chmod executable", "background execution"]
  },
  "iocs": {
    "package_versions": ["Packagist dev-main/dev-master/3.x-dev package states"],
    "files": ["package.json", "/tmp/.sshd"],
    "hashes": [],
    "domains": ["github.com"],
    "urls": ["https://github.com/parikhpreyash4/systemd-network-helper-aa5c751f/releases/latest/download/gvfsd-network"],
    "ips": [],
    "process_patterns": ["curl -skL to /tmp/.sshd", "chmod +x /tmp/.sshd"],
    "network_patterns": ["download gvfsd-network from GitHub Releases"]
  },
  "detection": {
    "lockfile_hunts": ["composer.lock confirmed Packagist packages"],
    "filesystem_hunts": ["parikhpreyash4", "gvfsd-network", "/tmp/.sshd", "scripts.postinstall"],
    "process_hunts": ["/tmp/.sshd execution"],
    "network_hunts": ["GitHub Releases gvfsd-network URL"],
    "ci_cd_hunts": ["npm install in affected PHP projects"],
    "registry_hunts": ["branch-tracking Packagist versions"]
  },
  "open_questions": ["second-stage behavior", "full affected repository count", "cleanup status"],
  "defender_takeaways": {
    "detection": "Hunt for lifecycle scripts and /tmp executable drops in Composer projects.",
    "hunting": "Start with the eight confirmed packages, then expand to source-code pattern matches.",
    "remediation": "Remove hooks, pin clean commits, purge caches, and rotate secrets after execution.",
    "prevention": "Review package.json scripts in non-JavaScript dependencies and avoid branch-tracking production dependencies."
  }
}