The most common mechanism for malicious code execution in supply chain attacks is not a sophisticated exploit. It is the post-install hook -- a feature that every major package manager supports and that runs arbitrary code automatically after a package is installed.
npm has postinstall scripts. pip has setup.py. gem has extconf.rb. Each of these lets package authors run code on the machine that installs their package. This feature exists for legitimate reasons (compiling native extensions, generating configuration files), but it is also the primary vector for every category of supply chain attack: typosquatting, dependency confusion, account takeover, and maintainer compromise.
How Each Ecosystem Handles Hooks
npm
npm supports lifecycle scripts defined in package.json: preinstall, install, postinstall, preuninstall, postuninstall, and others. The postinstall script is the most commonly abused.
When you run npm install, npm downloads packages and then executes their lifecycle scripts in dependency order. A malicious postinstall script can do anything the current user can do: read files, make network connections, install persistent backdoors.
npm added the --ignore-scripts flag to skip lifecycle scripts, but using it breaks packages that legitimately need post-install compilation. npm 7+ also added support for npm audit signatures to verify package provenance.
pip
Python source distributions execute setup.py during installation, which is effectively a pre-install hook. The setup.py file runs before any of the package code is installed, giving it first access to the build environment.
Wheel packages do not execute setup.py, making them inherently safer. But when wheels are not available, pip falls back to source distribution installation.
gem
RubyGems supports extconf.rb for compiling native extensions and post_install_message for displaying messages. The extconf.rb file runs arbitrary Ruby code during installation and is used for native extension compilation.
Additionally, gem specification supports an extensions field that lists scripts to run during installation. These scripts are intended for compilation but can execute any Ruby code.
Cargo
Rust Cargo uses build.rs scripts that run during compilation rather than installation. While technically a build hook rather than an install hook, the effect is the same: arbitrary code execution when you add a dependency.
Attack Patterns
Data exfiltration. The most common malicious hook payload reads environment variables (looking for cloud credentials, CI/CD tokens, and API keys) and sends them to an attacker-controlled server.
Reverse shells. Some malicious packages open a reverse shell connection, giving the attacker interactive access to the developer machine or CI/CD runner.
Cryptocurrency mining. Malicious hooks download and start cryptocurrency mining software that runs in the background consuming compute resources.
Source code theft. Hooks that read project source files and exfiltrate them to external servers. This targets proprietary code that the attacker can sell or use for competitive advantage.
Persistence. Hooks that modify shell profiles, cron jobs, or SSH authorized keys to maintain access after the package is removed.
Defensive Strategies
Disable hooks when possible. Use npm install --ignore-scripts for initial installation, then selectively enable scripts for packages that need them using .npmrc configuration.
Use lockfiles with integrity hashes. Lockfiles ensure that the exact same package version (with the same code) is installed every time. This prevents an attacker from substituting a malicious version between installs.
Prefer pre-built packages. Use npm packages without postinstall scripts, Python wheels instead of sdists, and binary gems when available. Pre-built packages skip the code execution step.
Sandbox package installation. Run npm install, pip install, and similar commands inside containers or VMs with restricted network access and minimal filesystem permissions.
Audit hooks before installation. For new dependencies, review their install hooks before adding them to your project. Check package.json scripts, setup.py, and extconf.rb files.
Monitor outbound network during installation. Legitimate install hooks compile code and generate files. They rarely need network access. Monitor for unexpected outbound connections during package installation.
How Safeguard.sh Helps
Safeguard.sh scans packages for malicious install hooks across npm, PyPI, and other ecosystems. Our platform detects common malicious patterns in post-install scripts, monitors package registries for newly published suspicious packages, and alerts you before compromised packages reach your development environment. Combined with SBOM generation, Safeguard.sh provides complete visibility into what runs on your systems during package installation.