T1195.001 Microsoft Sentinel · KQL

Detect Compromise Software Dependencies and Development Tools in Microsoft Sentinel

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/

KQL Detection Query

Microsoft Sentinel (KQL)
kusto
// T1195.001 — Compromised Software Dependencies: package manager spawning suspicious children + non-standard registry connections
let PackageManagerProcs = dynamic(["npm", "npm.cmd", "npm.exe", "node", "node.exe", "pip", "pip3", "pip.exe", "pip3.exe", "python", "python3", "python.exe", "python3.exe", "pipx", "yarn", "pnpm", "gem", "bundle", "cargo", "go", "nuget", "dotnet"]);
let SuspiciousChildProcs = dynamic(["powershell.exe", "pwsh.exe", "cmd.exe", "wscript.exe", "cscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe", "certutil.exe", "bitsadmin.exe", "curl.exe", "wget.exe"]);
let SuspiciousCommandPatterns = dynamic(["/dev/tcp", "base64 -d", "base64 --decode", "bash -i", "sh -i", "nc -e", "ncat -e", "python -c", "perl -e", "ruby -e", "DownloadString", "DownloadFile", "Invoke-Expression", "IEX(", "curl http", "wget http", "--registry http://", "--registry https://", "postinstall", "preinstall"]);
// Arm 1: Package managers spawning suspicious OS-level processes (postinstall/preinstall hook abuse)
let PackageManagerChildProc =
    DeviceProcessEvents
    | where Timestamp > ago(24h)
    | where InitiatingProcessFileName has_any (PackageManagerProcs)
    | where FileName has_any (SuspiciousChildProcs)
          or ProcessCommandLine has_any (SuspiciousCommandPatterns)
    | extend DetectionArm = "PackageManagerSpawnedSuspiciousChild"
    | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
             InitiatingProcessFileName, InitiatingProcessCommandLine,
             InitiatingProcessFolderPath, FolderPath, DetectionArm;
// Arm 2: Network connections from package manager child processes to non-standard or public IPs
let PackageManagerNetworkAnomalies =
    DeviceNetworkEvents
    | where Timestamp > ago(24h)
    | where InitiatingProcessFileName has_any (PackageManagerProcs)
    | where RemoteIPType == "Public"
    | where not (RemoteUrl has_any ("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"))
    | extend DetectionArm = "PackageManagerUnexpectedExternalConnection"
    | project Timestamp, DeviceName, AccountName = InitiatingProcessAccountName,
             FileName = InitiatingProcessFileName, ProcessCommandLine = InitiatingProcessCommandLine,
             RemoteUrl, RemoteIP, RemotePort, RemoteIPType, DetectionArm;
// Arm 3: CI/CD workflow file modifications (GitHub Actions poisoning)
let CICDWorkflowModifications =
    DeviceFileEvents
    | where Timestamp > ago(24h)
    | where FolderPath has_any (".github/workflows", ".gitlab-ci", "Jenkinsfile", ".circleci", ".travis", "azure-pipelines")
          or FileName has_any ("Makefile", "CMakeLists.txt", "build.gradle", "pom.xml") and ActionType in ("FileModified", "FileCreated")
    | where ActionType in ("FileModified", "FileCreated", "FileRenamed")
    | extend DetectionArm = "CICDPipelineFileModified"
    | project Timestamp, DeviceName, AccountName = InitiatingProcessAccountName,
             FileName, FolderPath, ActionType,
             InitiatingProcessFileName, InitiatingProcessCommandLine, DetectionArm;
// Union all arms
PackageManagerChildProc
| union PackageManagerNetworkAnomalies
| union CICDWorkflowModifications
| sort by Timestamp desc
high severity medium confidence

Multi-arm detection for T1195.001 supply chain compromises via software dependency poisoning. Arm 1 detects package managers (npm, pip, yarn, cargo, gem, etc.) spawning suspicious OS-level processes — the primary indicator of malicious preinstall/postinstall lifecycle hook execution. Arm 2 detects package manager processes making outbound network connections to non-standard registries or unexpected external IPs (exfiltration, C2 staging). Arm 3 detects modifications to CI/CD pipeline definition files (GitHub Actions workflows, Jenkinsfiles, etc.) which may indicate pipeline poisoning. Uses DeviceProcessEvents, DeviceNetworkEvents, and DeviceFileEvents tables.

Data Sources

Process: Process CreationNetwork Traffic: Network Connection CreationFile: File ModificationMicrosoft Defender for Endpoint

Required Tables

DeviceProcessEventsDeviceNetworkEventsDeviceFileEvents

False Positives & Tuning

  • Legitimate npm packages with postinstall scripts that compile native binaries (node-gyp, esbuild, sharp) — these frequently spawn cmd.exe or bash
  • Developer tools that legitimately use non-standard registries (Artifactory, Nexus, Azure Artifacts, private npm mirrors) for corporate package management
  • CI/CD automation committing workflow file updates as part of normal GitOps or automated dependency update PRs (Dependabot, Renovate)
  • Python packages with C extensions running compiler toolchains (gcc, cl.exe, link.exe) via setup.py during installation
  • Security scanning tools (Snyk, FOSSA, Trivy) that inspect packages and may trigger file access patterns
Download portable Sigma rule (.yml)

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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

Unlock Pro Content

Get the full detection package for T1195.001 including response playbook, investigation guide, and atomic red team tests.

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections