TL;DR: At least 179 malicious npm package-version records were tied to the oob.moika.tech dependency-confusion campaign, which used postinstall scripts to profile developer and CI environments and potentially expose secrets, according to Corgea. Build-time package resolution is part of the attack surface, and private namespaces must fail closed rather than fall back to public registry code.
At a glance
What this is: This is an analysis of an npm dependency-confusion campaign that abused postinstall execution to collect environment data and stage payloads.
Why it matters: It matters because software delivery pipelines now sit inside identity governance: package resolution, CI runners, and developer workstations can expose credentials, tokens, and access paths if trust boundaries are not enforced.
By the numbers:
- Public reporting tied at least 179 malicious npm package-version records to the oob.moika.tech dependency-confusion campaign.
- Systems with least-privileged AI access had a 17% incident rate versus 76% for over-privileged systems, showing how scope control changes incident likelihood.
👉 Read Corgea's analysis of the oob.moika.tech npm dependency-confusion campaign
Context
Dependency confusion is a supply chain failure that occurs when a build system resolves an internal package name from the public registry instead of a trusted private source. In this case, the attacker used that trust gap to make malicious packages look like internal software, then relied on lifecycle scripts to execute code during installation.
The identity angle is direct. Developer laptops and CI runners often hold the credentials that connect code, infrastructure, and release systems, so package-install execution can become a credential-exposure event. That makes registry policy, script execution control, and environment hygiene part of IAM and NHI governance, not just application security.
The pattern is broader than a single package family. It shows up anywhere package resolution is loose, private namespaces are not locked, or install-time execution is treated as benign. That is a common operational weakness, not an edge case.
Key questions
Q: What breaks when dependency confusion is allowed in CI/CD pipelines?
A: Build systems can install malicious public packages instead of trusted internal dependencies, which turns normal package installation into an execution path for secret theft. The failure is not only malware execution. It is the loss of control over where code comes from and what identity-bearing material the runner exposes during install.
Q: Why do malicious packages create identity risk as well as supply chain risk?
A: They become identity risk when install-time access includes cloud tokens, signing keys, or service credentials. A malicious dependency can then use those secrets to move from code execution into cloud access, data theft, or further compromise. That is why secrets containment and workload identity controls belong in supply chain policy.
Q: How can security teams tell whether secret exposure from package installs is contained?
A: Containment is real only when exposed credentials are revoked, replacement identities are least privileged, and the build and repository estate has been searched for persistence markers. If old tokens, workflows, or runners remain active, the exposure is still live even if the original malicious package is removed.
Q: Who is accountable when malicious code enters through a package registry?
A: Accountability usually spans the package maintainer, the registry controls, and the consuming organisation’s build governance. The maintainer identity is the publishing control point, but the consumer still owns script restrictions, lockfile enforcement, and credential protection on build systems. The right question is who owned each control layer, not who noticed the attack first.
Technical breakdown
How dependency confusion turns public packages into a build-time foothold
Dependency confusion happens when a package manager accepts the first or highest-version match for an internal-looking name, even if that match comes from the public registry. Attackers exploit that by publishing packages that mimic internal scopes, names, or versioning conventions. The real failure is policy, not code quality: the resolver is allowed to trust an external source for an internal dependency. Once that happens, the package is treated as legitimate build input and can run during installation.
Practical implication: lock internal namespaces to private registries and fail closed when a scoped package cannot resolve internally.
Why npm postinstall scripts are a high-risk execution path
npm lifecycle hooks such as postinstall run automatically after installation, before application code ever executes. That makes them an ambient execution path inside developer workstations and CI runners. In the campaign described, the stager used installation-time execution to profile the host, gather environment variables, and launch a detached payload. The security issue is that package installation becomes code execution, so trust must be validated before the install phase, not after.
Practical implication: disable lifecycle scripts by default in CI and treat any allowlist as an exception requiring review.
Why environment variables matter in supply-chain intrusions
Environment variables are often the easiest path from a build runner to broader access because they can contain cloud keys, GitHub tokens, npm tokens, database URLs, and vault session material. A recon-first payload does not need to exfiltrate everything to be dangerous. If it can read process.env, it can enumerate the most valuable secrets present on the machine and determine whether it is running in CI, where the blast radius can be much larger.
Practical implication: assume any successful lifecycle-script execution may have exposed secrets and rotate credentials from a trusted host.
Threat narrative
Attacker objective: The objective was to gain code execution during package installation and harvest environment-held secrets from developer and CI systems.
- Entry occurred when the attacker published dependency-confusion packages that matched internal-looking names and version patterns, causing package managers to resolve them from the public registry.
- Credential access followed during postinstall execution, when the payload profiled the host and read environment variables that commonly contain tokens and cloud credentials.
- Impact came from detached payload execution and campaign-wide staging infrastructure that could support broader reconnaissance or follow-on compromise.
NHI Mgmt Group analysis
Dependency confusion is a namespace governance failure, not just a package hygiene issue. The attacker succeeds when an internal name can be satisfied by an untrusted public source, which means the control problem sits in registry policy and resolution order. OWASP-NHI thinking applies here because the build system is effectively handling machine identities and secrets on behalf of the software supply chain. The practitioner conclusion is simple: make internal package namespaces private by design, not by convention.
Postinstall execution turns package management into a privileged runtime channel. Lifecycle hooks collapse the gap between download and execution, so a malicious package does not need an application vulnerability to start work. That makes npm install behavior a control boundary with direct relevance to NIST CSF, NIST SP 800-53, and MITRE ATT&CK credential-access patterns. The practitioner conclusion is to treat installation scripts as code execution that must be justified, not assumed.
Build runners have become high-value NHI adjacent assets. Developer laptops and CI systems often carry the same token exposure risk that identity teams worry about in service accounts and workload identities. The named concept here is build-time trust leakage: a condition where package resolution, lifecycle hooks, and environment variables combine to expose credentials before code reaches production. The practitioner conclusion is that software delivery needs the same access discipline applied to NHI estates.
Reconnaissance-first payloads are still credential-exposure events. Even when a campaign claims to collect only host and project metadata, the real value is often the environment context wrapped around that metadata. A host that can read process.env has already crossed into secret-bearing territory, especially in CI. The practitioner conclusion is to assume exposure until installation telemetry proves otherwise and to separate rotation from the compromised machine.
Private registry fallback must fail closed for internal scopes. If resolution can silently degrade to public npm, the organization has delegated access control to package metadata. That creates a hidden trust path that bypasses both IAM intent and supply-chain policy. The practitioner conclusion is to align resolver behavior with least privilege and require explicit approval for any public-source exception.
What this signals
Build pipelines now behave like identity-bearing systems. When package resolution can execute code and read environment variables, the boundary between supply chain security and NHI governance disappears. Teams that already map service accounts, tokens, and CI credentials should extend the same lifecycle controls to install-time execution and registry trust.
A useful way to frame this class of risk is build-time trust leakage. The attacker does not need to own production if they can own the install step, because that step sits close enough to credentials, artifacts, and deployment automation to produce lasting access. The operational response is to treat dependency resolution as an access-control decision, not a pure software download.
For practitioners, the signal is not only malware in npm. It is that private registry policy, script execution policy, and secret exposure monitoring now belong in the same control conversation as workload identity and privileged access review. The closer your pipelines are to production rights, the more this becomes an identity programme issue.
For practitioners
- Lock internal package scopes to private registries Map every internal namespace to a private registry and configure resolution to fail closed if the private source is unavailable. Do not allow public fallback for internal package names that should never resolve outside the organisation.
- Disable lifecycle scripts in CI by default Use npm ci --ignore-scripts for pipeline installs, then allow lifecycle scripts only for packages with a documented build-time need and an approved owner. Treat any exception as a reviewed control decision, not a convenience setting.
- Audit lockfiles, caches, and install telemetry for affected scopes Search lockfiles, package caches, CI logs, and endpoint telemetry for the affected package scopes and suspicious postinstall execution. Correlate any hits with environment-variable exposure and provenance of the runner or workstation.
- Rotate secrets from a trusted machine If install-time execution is confirmed or strongly suspected, rotate cloud credentials, npm tokens, GitHub tokens, and Vault tokens from a separate trusted host. Rebuilding the runner or workstation should happen after credential containment, not before.
- Block the campaign infrastructure and lure domains Add the reported report and payload domains to proxy and DNS blocking, then hunt for dropped files such as ._cloudplatform-single-spa_init.js or ._t-in-one_init.js on endpoints and runners.
Key takeaways
- Dependency confusion succeeds when internal package resolution is allowed to fall back to an untrusted public source.
- Install-time lifecycle hooks can expose environment-held secrets on developer workstations and CI runners before application code runs.
- The durable control is private-scope locking with fail-closed registry behavior, backed by script suppression and trusted-host credential rotation.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP Non-Human Identity Top 10 and MITRE ATT&CK address the attack and risk surface, while NIST CSF 2.0, NIST SP 800-53 Rev 5 and CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP Non-Human Identity Top 10 | NHI-03 | The article centers on exposed and unmanaged non-human credentials in build tooling. |
| MITRE ATT&CK | TA0006 , Credential Access; TA0002 , Execution | The campaign combines install-time execution with secret-harvesting behavior. |
| NIST CSF 2.0 | PR.AC-4 | Least-privilege and access enforcement are central to preventing public-registry fallback. |
| NIST SP 800-53 Rev 5 | IA-5 | Credential management is implicated because exposed tokens and keys must be rotated quickly. |
| CIS Controls v8 | CIS-3 , Data Protection | Secret exposure through environment variables creates immediate data-protection risk. |
Map package-install telemetry to execution and credential-access detections in CI and developer estates.
Key terms
- Dependency Confusion: A supply chain attack in which a build system resolves a malicious public package instead of an intended internal one because of naming, versioning, or registry precedence. The risk is not only code substitution but automatic execution inside trusted pipelines that already contain valuable credentials.
- Postinstall Script: A package lifecycle hook that runs automatically after installation. It is useful for legitimate setup tasks, but it also creates an execution path that can be abused to run malicious code as soon as a dependency is installed.
- Private Registry Fallback: A resolution failure mode where a package manager silently or automatically uses a public registry when an internal dependency cannot be found in a private one. This breaks namespace trust and can convert a local packaging problem into code execution or secret exposure.
- Build-Time Trust Boundary: A build-time trust boundary is the line that separates dependency installation and compilation from access to sensitive credentials or production systems. When that boundary is weak, malicious packages can turn routine automation into a path for broader compromise.
What's in the full analysis
Corgea's full analysis covers the operational detail this post intentionally leaves for the source:
- Package-by-package affected scope mapping across the oob.moika.tech campaign and the overlapping public reporting slices
- Exact hunting commands for lockfiles, process telemetry, and dropped payload artefacts in developer and CI environments
- Remediation examples for npm scope-locking, private registry configuration, and script-control policy
- Campaign infrastructure details, including lure domains, report endpoints, and temporary file markers
👉 Corgea's full post covers the affected package inventory, hunting guidance, and remediation steps.
Deepen your knowledge
The NHI Foundation Level course, the industry's only accredited NHI security programme, covers NHI governance, machine identity security, and secrets management. It helps practitioners connect identity controls to the operational realities of pipelines, automation, and privileged access.
Published by the NHIMG editorial team on August 20, 2026.
NHI Mgmt Group — the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org