Curl Download Activity from npm Package Install

Last updated 10 days ago on 2026-11-03
Created 2 months ago on 2026-09-23

About

Detects curl downloading over HTTP(S) with a short argument list, writing output to a file or launched via a shell, when the process ancestry includes a Node.js npm package execution (`npx-cli.js` or an npx cache path). Malicious npm packages and supply-chain compromises commonly fetch a second stage from install or postinstall scripts.
Tags
Domain: EndpointOS: LinuxOS: macOSPlatform: LinuxPlatform: macOSUse Case: Threat DetectionTactic: Command and ControlTactic: ExecutionTactic: Initial AccessData Source: Elastic DefendRule Type: ES|QLThreat: Supply ChainThreat: Download Tool AbuseLanguage: esql
Severity
medium
Risk Score
47
MITRE ATT&CK™

Command and Control (TA0011)(external, opens in a new tab or window)

Execution (TA0002)(external, opens in a new tab or window)

Initial Access (TA0001)(external, opens in a new tab or window)

License
Elastic License v2(external, opens in a new tab or window)

Definition

Integration Pack
Prebuilt Security Detection Rules
Related Integrations

endpoint(external, opens in a new tab or window)

Query
text code block:
FROM logs-endpoint.events.process-* METADATA _id, _version, _index | WHERE KQL(""" host.os.type:("linux" or "macos") AND event.action:exec """) | EVAL is_pkg_install = CASE( // npm process.parent.name == "node" AND ( process.parent.command_line LIKE "*npx-cli.js*" OR process.parent.command_line LIKE "*npm-cli.js*" OR process.parent.command_line LIKE "*/.npm/_npx/*" OR process.parent.command_line LIKE "*/npm-cache/*" ), true, false ) | EVAL cmdline_lower = TO_LOWER(process.command_line) | EVAL parent_cmdline_lower = TO_LOWER(process.parent.command_line) | EVAL is_curl_download = CASE( process.name == "curl" AND cmdline_lower LIKE "*http*" AND process.args_count <= 5 AND ( cmdline_lower LIKE "* -o*" OR cmdline_lower LIKE "* --output*" OR parent_cmdline_lower LIKE "*zsh" OR parent_cmdline_lower LIKE "*sh" OR parent_cmdline_lower LIKE "*bash" OR parent_cmdline_lower LIKE "*dash" ) AND NOT ( cmdline_lower LIKE "*169.254.169.254*" OR cmdline_lower LIKE "*localhost*" OR cmdline_lower LIKE "*127.0.0.1*" ), true, false ) | WHERE process.Ext.ancestry IS NOT NULL AND (is_curl_download OR is_pkg_install) // Capture entity_ids for package install parent processes | EVAL all_entity_id = CASE(is_pkg_install, process.parent.entity_id, "null") // Collect all package install entity_ids globally | INLINE STATS all_pkg_entity_ids = VALUES(all_entity_id), all_pkg_cmdline = VALUES(process.parent.command_line) WHERE all_entity_id != "null" by host.id // Find which package install entity_ids appear in this process's ancestry | EVAL Esql.pkg_ancestor_ids = MV_INTERSECTION(all_pkg_entity_ids, process.Ext.ancestry) // curl download descended from an npm package install process | WHERE Esql.pkg_ancestor_ids IS NOT NULL AND is_curl_download | KEEP _id, _version, _index, data_stream.namespace, host.id, host.name, user.name, process.entity_id, process.executable, process.command_line, process.parent.executable, process.parent.command_line, all_pkg_cmdline

Install detection rules in Elastic Security

Detect Curl Download Activity from npm Package Install in the Elastic Security detection engine by installing this rule into your Elastic Stack.

To setup this rule, check out the installation guide for Prebuilt Security Detection Rules(external, opens in a new tab or window).