Detect Compromise Software Dependencies and Development Tools in Elastic Security
Adversaries manipulate software dependencies and development tools prior to receipt by a final consumer to compromise data or systems. This includes injecting malicious code into popular open source packages (npm, PyPI, RubyGems), registering typosquatted or abandoned package names, and poisoning CI/CD pipeline components such as GitHub Actions. Malicious packages commonly use preinstall/postinstall lifecycle hooks to execute arbitrary OS commands at install time, enabling immediate credential theft, reverse shell establishment, or persistent implant deployment. Detection focuses on package manager processes spawning unexpected child processes, outbound network connections from package manager child processes, CI/CD workflow file modifications, and installation from non-standard or suspicious registries.
MITRE ATT&CK
- Tactic
- Initial Access
- Technique
- T1195 Supply Chain Compromise
- Sub-technique
- T1195.001 Compromise Software Dependencies and Development Tools
- Canonical reference
- https://attack.mitre.org/techniques/T1195/001/
Elastic Detection Query
any where
(
// Arm 1: Package manager spawning suspicious child processes (postinstall/preinstall hook abuse)
event.category == "process" and event.type == "start" and
process.parent.name in~ ("npm", "npm.cmd", "node", "node.exe", "pip", "pip3", "pip.exe", "pip3.exe", "python", "python3", "python.exe", "python3.exe", "pipx", "yarn", "pnpm", "gem", "bundle", "cargo", "go", "nuget", "dotnet") and
(
process.name in~ ("powershell.exe", "pwsh.exe", "cmd.exe", "wscript.exe", "cscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe", "certutil.exe", "bitsadmin.exe", "curl.exe", "wget.exe") or
process.command_line like~ ("*/dev/tcp*", "*base64 -d*", "*base64 --decode*", "*bash -i*", "*sh -i*", "*nc -e*", "*ncat -e*", "*python -c*", "*perl -e*", "*DownloadString*", "*DownloadFile*", "*Invoke-Expression*", "*IEX(*", "*curl http*", "*wget http*", "*--registry http*", "*postinstall*", "*preinstall*")
)
)
or
(
// Arm 1b: Lifecycle hook parent spawning suspicious process
event.category == "process" and event.type == "start" and
process.parent.command_line like~ ("*postinstall*", "*preinstall*", "*install.js*", "*setup.py*", "*node-pre-gyp*") and
process.name in~ ("powershell.exe", "pwsh.exe", "cmd.exe", "wscript.exe", "cscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe", "certutil.exe", "bitsadmin.exe", "curl.exe", "wget.exe")
)
or
(
// Arm 2: Package manager processes making unexpected external network connections
event.category == "network" and event.type == "connection" and
network.direction == "egress" and
process.name in~ ("npm", "node", "node.exe", "pip", "pip3", "python", "python3", "yarn", "pnpm", "gem", "bundle", "cargo", "go") and
not destination.domain in~ ("registry.npmjs.org", "pypi.org", "files.pythonhosted.org", "rubygems.org", "crates.io", "nuget.org", "pkg.go.dev", "proxy.golang.org", "yarnpkg.com", "registry.yarnpkg.com")
)
or
(
// Arm 3: CI/CD pipeline and build file creation or modification
event.category == "file" and event.type in ("creation", "change") and
(
file.path like~ ("*/.github/workflows/*", "*/.gitlab-ci*", "*/Jenkinsfile*", "*/.circleci/*", "*/.travis*", "*/azure-pipelines*") or
file.name in~ ("Makefile", "CMakeLists.txt", "build.gradle", "pom.xml")
)
) Detects T1195.001 supply chain compromise via four conditions mapped to three detection arms: (1a) package managers (npm, pip, yarn, gem, cargo, dotnet, go) spawning suspicious OS-level child processes indicative of postinstall/preinstall lifecycle hook abuse; (1b) CI/CD lifecycle hook commands directly spawning LOLBins; (2) package manager processes establishing egress connections to destinations outside known-good package registries; (3) creation or modification of CI/CD pipeline configuration files including GitHub Actions workflows, GitLab CI, Jenkinsfile, and Azure Pipelines. Uses Elastic Common Schema (ECS) fields across process, network, and file event categories.
Data Sources
Required Tables
False Positives & Tuning
- Legitimate postinstall scripts in well-known packages (e.g., node-gyp native module compilation for bcrypt, canvas, sharp) that invoke cmd.exe or sh to compile native C/C++ bindings — validate against package name, build directory path, and developer workstation context
- Developer scaffolding tools (create-react-app, vue-cli, angular-cli) that legitimately spawn shell processes to scaffold project templates, run database migrations, or execute build steps during initial npm install on developer machines
- Authorized CI/CD pipeline updates by DevOps engineers or automated bots (Dependabot, Renovate) modifying GitHub Actions workflow YAML files or Jenkinsfiles as part of normal release engineering — correlate with known automation service account identities and branch naming conventions
Other platforms for T1195.001
Testing Methodology
Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Simulated Malicious npm postinstall Hook
Expected signal: Sysmon Event ID 1: npm.cmd spawning cmd.exe with CommandLine containing 'whoami'. Sysmon Event ID 11: file creation at %TEMP%\argus-npm-test.txt. DeviceProcessEvents: InitiatingProcessFileName=npm.cmd, FileName=cmd.exe.
- Test 2Malicious pip setup.py Simulating Credential Exfiltration Pattern
Expected signal: Sysmon for Linux (or auditd): process creation with ParentProcess=python3/pip, ChildProcess=id or sh. Auditd syscall execve with ppid of pip process. Syslog: process accounting entry for 'id' with parent pip.
- Test 3Simulated GitHub Actions Workflow Poisoning
Expected signal: Sysmon Event ID 11 (FileCreated): TargetFilename ending in .github\workflows\ci.yml, InitiatingProcessFileName=cmd.exe. DeviceFileEvents: FileName=ci.yml, FolderPath contains .github/workflows, ActionType=FileCreated.
- Test 4npm Package Install from Non-Standard Registry (Registry Confusion)
Expected signal: Sysmon EventCode=3 (Network Connection): Image=node, DestinationIp=127.0.0.1, DestinationPort=4873, DestinationHostname not in standard registry allowlist. DeviceNetworkEvents: InitiatingProcessFileName=node, RemotePort=4873.
References (12)
- https://attack.mitre.org/techniques/T1195/001/
- https://www.paloaltonetworks.com/blog/cloud-security/github-actions-worm-dependencies/
- https://unit42.paloaltonetworks.com/github-actions-supply-chain-attack
- https://checkmarx.com/zero-post/python-pypi-supply-chain-attack-colorama/
- https://thehackernews.com/2024/09/hackers-hijack-22000-removed-pypi.html
- https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-04-Poisoned-Pipeline-Execution
- https://hackread.com/backdoors-python-npm-packages-windows-linux/
- https://www.bitdefender.com/en-gb/blog/hotforsecurity/popular-npm-repositories-compromised-in-man-in-the-middle-attack
- https://www.trendmicro.com/vinfo/dk/security/news/cybercrime-and-digital-threats/hacker-infects-node-js-package-to-steal-from-bitcoin-wallets
- https://checkmarx.com/blog/new-technique-to-trick-developers-detected-in-an-open-source-supply-chain-attack/
- https://cyberpress.org/malicious-npm-and-pypi-packages-disguised-as-dev-tools
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1195.001/T1195.001.md
Unlock Pro Content
Get the full detection package for T1195.001 including response playbook, investigation guide, and atomic red team tests.