The package can appear to behave like a normal dependency while quietly spawning a second-stage payload. In this pattern, JavaScript code starts Python, installs required libraries, and launches the malicious script from a local file. That lets the attacker use the NPM ecosystem for distribution while the actual theft logic runs in Python.
What the malicious package is really doing
A package like this is abusing the trust model of the NPM ecosystem, not just hiding bad code. The JavaScript layer acts as the delivery wrapper: it looks like ordinary dependency logic, then quietly launches a Python stage that can carry out the theft outside the more visible JavaScript path. That split is deliberate, because it helps the attacker blend into normal developer workflows while separating distribution from payload execution.
The practical effect is that defenders who only inspect package metadata, install scripts, or JavaScript source can miss the real activity. The visible package may appear to do little more than bootstrap a local process, but that bootstrap step is enough to transfer control to a second interpreter and run a separate malicious file. In supply-chain terms, the package is functioning as a loader, not just a library.
When that second stage runs, the attacker gains more room to install dependencies, read local files, enumerate environment variables, or reach out to external infrastructure without tying all of those actions directly to the original NPM entrypoint. The pattern is especially useful to attackers because it lets them hide the theft logic in a different runtime while keeping the initial package simple enough to pass casual review.
Why this pattern is effective in supply-chain attacks
This works because modern build and install pipelines often trust package-manager behaviour more than they should. A malicious dependency can invoke local tooling, spawn child processes, and fetch or install runtime components during installation or execution. If the package has enough legitimate-looking structure, the malicious handoff to Python may only look like a compatibility step or a helper process.
The technique also broadens the attacker’s reach. An NPM package can distribute quickly through the JavaScript ecosystem, while Python can be used for the actual collection logic, parsing, process interaction, or exfiltration. That makes detection harder because the malicious behaviour is split across two ecosystems, two sets of tooling, and often two different review assumptions.
For practitioners, the important point is that the compromise is not limited to a single package manager. Once a dependency is trusted enough to execute code, any secondary runtime it launches becomes part of the attack surface. That is why supply-chain review has to include process creation, child interpreters, postinstall behaviour, and file-system writes, not just source-level inspection of the top-level language.
Supply-chain abuse in open source is not hypothetical. The broader ecosystem threat is well documented by the OpenSSF supply-chain work, and NPM-specific malware campaigns such as Shai Hulud npm malware campaign show how quickly malicious package can pivot from distribution to secrets theft.
What defenders should verify first
Start with execution visibility, not just package allowlists. You want to know whether an NPM install or postinstall hook is spawning Python, whether that Python process is pulling libraries dynamically, and whether the resulting script is executing from a local path that was dropped or unpacked by the package. Those are the concrete signals that separate a normal dependency from a staged loader.
Then check what the second stage can access. If the package can read developer tokens, cloud credentials, CI secrets, SSH material, or other sensitive files from the host, the impact is no longer limited to a suspicious dependency. It becomes a credential exposure problem with immediate blast-radius implications, especially in build agents, developer workstations, and shared automation runners.
Use repository and endpoint telemetry together. Source review can show the JavaScript launch path, but process telemetry is what confirms whether Python was invoked and whether the expected file and network activity followed. On the defensive side, supply-chain guidance from SLSA is useful for build provenance, while OWASP API Security Top 10 is a good reminder that stolen tokens and broken trust boundaries are often the downstream consequence, not the starting point.
For identity and secret exposure in open source ecosystems, the most relevant NHIMG material is LiteLLM PyPI package breach, which shows the same trust-to-theft pattern from a different package-manager angle, and Miasma and Hades Supply Chain Worms, which shows how compromise can spread across ecosystems and credential stores.
Risk and Threat Considerations
This pattern is risky because it turns a dependency install into an execution bridge. The visible package may be only the first step, while the real payload runs in a second interpreter that defenders are less likely to inspect closely. That increases the chance of secrets theft, credential reuse, and lateral movement from a developer or CI environment into higher-value systems.
Failure mechanism: The attacker uses the trusted NPM entrypoint to spawn Python, then runs a separate local script that can evade shallow code review, package reputation checks, and language-specific scanning.
Impact: Exposed tokens, API keys, and local credentials can be harvested quickly, and the compromised workstation or build agent can become a launch point for broader supply-chain compromise.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
MITRE ATT&CK and OWASP Agentic AI Top 10 address the attack and risk surface, while CIS Controls v8 and NIST CSF 2.0 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| CIS Controls v8 | CIS 2 — Software Inventory | This attack abuses untrusted package software in the supply chain. |
| CIS 4 — Secure Configuration of Enterprise Assets and Software | The malicious package relies on permissive runtime and install behaviour. | |
| CIS 6 — Access Control Management | The payload’s goal is often to reach secrets and tokens with excessive access. | |
| Recommendation — Inventory all software and packages to flag unapproved dependencies before installation. Harden development endpoints and build agents to restrict script execution and child processes. Remove unnecessary access paths so stolen secrets cannot reach high-value systems. | ||
| MITRE ATT&CK | T1105 — Ingress Tool Transfer | The second-stage stealer can be fetched or assembled after initial package execution. |
| T1059 — Command and Scripting Interpreter | The package launches Python as a scripting interpreter for malicious execution. | |
| T1552 — Unsecured Credentials | The stealer’s purpose is to collect secrets from local files and environments. | |
| Recommendation — Detect secondary payload retrieval and unexpected runtime downloads. Monitor for unexpected interpreter spawning from package install or app startup paths. Hunt for secrets access and rotate exposed credentials immediately. | ||
| NIST CSF 2.0 | GV.1 — Organizational Context | Supply-chain trust decisions depend on governance for third-party software. |
| PR.PS — Platform Security | Defensive value comes from controlling how packages execute on endpoints and build systems. | |
| DE.CM — Continuous Monitoring | The compromise is best detected through process and file telemetry. | |
| Recommendation — Define approval criteria for external dependencies and runtime execution. Restrict script execution and runtime privileges on developer and CI platforms. Continuously monitor for anomalous child processes and suspicious file access. | ||
| OWASP Agentic AI Top 10 | A1 — Agent Goal Manipulation | The staged loader pattern is about hijacking execution authority across components. |
| Recommendation — Constrain runtime actions so untrusted code cannot redirect execution to hidden payloads. | ||
Practitioner Guidance
What to verify: Treat any package that launches a second interpreter as higher scrutiny. Confirm whether the execution is necessary, whether the child process is expected, and whether the package writes files or downloads code during install or first run.
Decision rule: If a dependency can spawn Python and reach local secret material, assume it has blast radius beyond its declared function and prioritize containment, credential review, and provenance checks before relying on the package for anything production-adjacent.
What practitioners underestimate: The malicious value is often in the handoff, not the visible script. A small JavaScript wrapper can be enough to get a full Python stealer running, so language-specific review alone is not a sufficient control.
Practitioner takeaway: The key judgement is to inspect cross-runtime behaviour as one attack chain, because once a trusted package can launch another interpreter, the real security question becomes what that second stage can reach and steal.
Related resources from NHI Mgmt Group
- What happens when a malicious npm package uses postinstall hooks to persist on a developer machine?
- What breaks when a malicious Python package uses startup hooks instead of a normal import path?
- What happens when a malicious npm package is installed before the build even starts?
- How should security teams reduce the risk of malicious Python wheels being hidden inside otherwise legitimate package releases?
Deepen Your Knowledge
Reviewed and updated by the NHIMG editorial team on September 17, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org