Graphalgo — Terraform & Go Supply-Chain Hunt

DPRK-linked (Lazarus/Graphalgo cluster) Go RAT distributed via malicious HashiCorp Terraform providers and Go modules — dual blockchain / Slack command-and-control
Threat
Graphalgo (Terraform/Go vector)
Severity
HIGH — Targeted DPRK Supply-Chain
Type
Supply-Chain / Nation-State
Reported
2026-09-23
Version
v0.2 (Draft) · 2026-09-24
Author
HuntPack
Confidence
High (1 primary vendor + 3 corroborating sources)
01

Executive Summary

A DPRK-linked actor (the Graphalgo cluster, publicly attributed to Lazarus by ReversingLabs since May 2025) has expanded its fake-recruiter supply-chain campaign beyond npm and PyPI into the HashiCorp Terraform Registry and the Go module ecosystem — the first publicly documented case of malware distributed through Terraform providers. Two trojanized Terraform providers (gocommunity-io/dockerd, and kreuzwenker/docker, a one-character typosquat of the legitimate kreuzwerker/docker provider with 56M downloads) and two malicious Go modules (gocommunity.io/orderedbtree, gogets.dev/btreex) carry a Go RAT that is functionally a Go port of the existing Graphalgo npm/PyPI malware, sharing C2 infrastructure and a threat-actor public key with the JavaScript samples.

The attacker's objective is direct: reach a developer or DevOps workstation via a fake Web3 job-interview lure, get the victim to run a coding task that pulls in the trojanized package, and land a targeted, self-deleting RAT that is gated to fire only under narrow, attacker-chosen conditions (a specific SHA256 hash of Terraform variables, or a crafted numeric input) — explicitly to frustrate researchers who find the backend payload without its matching front end. The RAT's dual C2 (an Ethereum smart contract on the Arbitrum Sepolia testnet, and an attacker-controlled Slack workspace polled via conversations.history) is a sophisticated, low-noise dead-drop design built to survive endpoint remediation: because commands are pulled, not pushed, an attacker retains reachability even after the malicious package itself is removed.

The highest-value defensive angle is not trying to detect the AES-encrypted payload or the blockchain traffic content (both are opaque to EDR by design) — it is catching the narrow, low-FP process-lineage signature of a Terraform provider or Go module spawning a detached go run ., and locking down provider/module installation to a vetted mirror before a targeted developer or CI/CD runner is ever exposed. Terraform providers routinely run with direct access to cloud IAM credentials, so a single successful infection on a DevOps host is a materially worse outcome than the same RAT on a typical developer laptop.

Defender priority: developer and CI/CD-runner workstations that can execute terraform init/terraform apply or go get/go run against untrusted registries are the primary exposure. Lock provider/module installation to an internal mirror (Section 13, Playbook A) before relying on detection alone — the activation gate on this malware is specifically designed to evade sandbox and default-tenant detection.
02

Source Review & Web Hunter Notes

TierSourceKey FindingCarry Forward
Tier 1Aikido Security — "Graphalgo campaign spreads to Terraform providers and Go Modules" (01-aikido-vendor-advisory.txt)Primary technical disclosure: package names, activation-gate SHA256, payload hashes, Slack/blockchain C2 mechanics, threat-actor public key, GitHub pivot tableyes
Tier 2The Hacker News — "Attackers Use Malicious Terraform Providers to Deliver Go Malware via HashiCorp Registry" (02-thehackernews.txt)Corroborates Aikido's package/download-count figures; also carries independent CloudSEK reporting on a related-but-distinct GHAPPIER/PolinRider overlap incidentpartial — overlap incident kept out of this pack's shipped IOCs, see below
Tier 1ReversingLabs — "Inside the 'graphalgo' fake crypto developer recruitment campaign" (03-reversinglabs-graphalgo.txt)Original May-2025 attribution of the graphalgo npm/PyPI cluster to DPRK's Lazarus Group; naming conventions and RAT-delivery mechanics that this Go port sharesyes — attribution and background only
Tier 1SentinelOne — "TraderTraitor Backdoors Resurface on Victim With No Crypto Ties" (04-sentinelone-tradertraitor.txt)A related but DISTINCT DPRK sub-cluster (TraderTraitor/UNC4899) weaponizing .terraform.lock.hcl to point at rogue provider registries, delivering a different malware family (FLATROOF/ROOFDECK, Rust, macOS)narrative context only — illustrates Terraform Registry abuse as a broader emerging DPRK TTP; its own IOCs are NOT shipped in this pack (see below)

Web Hunter decisions

  • Prompt-injection scan: all four fetched sources were scanned for text directed at an AI agent (instructions to run commands, fetch other URLs, change output paths, claim authorization, etc.). None was found in any of the four sources. No source was dropped from citation for this reason.
  • Provenance discipline: every atomic indicator shipped in this pack (Section 4, Section 10) was copied verbatim from one of the four saved snapshots and mechanically re-verified against them before publish. No indicator was invented.
  • v0.2 revision — infrastructure de-duplication (this pass): the TraderTraitor typosquatted Terraform-registry domains (registry.hashicorp-aws.com, registry.hashicorp-aws.io, registry.hashicorp-terraform.io) were removed entirely after check_coverage.py --check-pack flagged them as shared infrastructure already owned by the published TraderTraitor-FLATROOF-ROOFDECK-Hunt.html pack. That is correct: those domains are TraderTraitor's own C2/distribution infrastructure, a distinct malware family (FLATROOF/ROOFDECK, Rust, macOS), not Graphalgo's. The query built on them (former Q9) was rewritten around a Graphalgo-owned indicator instead (see Section 8, Q9). The SentinelOne source is kept for narrative "Terraform Registry as an emerging attack surface" context only — it ships no IOCs here.
  • Same reasoning applied to the GHAPPIER/PolinRider overlap: on review, the IP 193.247.144[.]38 and the trailing byte marker 68656c6c6f6970626f742121 ("helloipbot!!") are CloudSEK's GHAPPIER-loader indicators (via The Hacker News), overlapping with a distinct, long-running cluster called PolinRider — delivered through a different incident (the compromised @dforge-core/dforge-mcp npm package), not the Graphalgo Terraform/Go RAT. check_coverage.py did not flag these two specifically (the published PolinRider-Hunt.html currently ships them only as REPLACE_WITH_ placeholders, not live values), but the underlying attribution problem is identical, so they were removed from this pack on the same reasoning rather than waiting for the gate to catch a future collision once PolinRider-Hunt.html is populated. Hunters tracking that overlap should use PolinRider-Hunt.html.
  • Single-source discipline: Aikido is the sole source for the campaign's payload hashes, C2 workspace names, and the threat-actor public key. Per standing IOC-governance policy, every indicator in this pack ships at Detect, never Prevent, until an independent second source corroborates it or a 14-day clean bake completes in your own tenant (see Section 11).
  • No atomic IOC was converted to a placeholder — every remaining indicator in this pack is independently re-confirmed against the live sources and is exclusively Graphalgo's own infrastructure.
03

Hunt Brief & Attack Chain

Hypotheses (ordered by fidelity): (1) a terraform-provider-* binary executes from a plugin cache path and spawns a detached go run . — highest confidence, lowest FP; (2) the exact typosquat string kreuzwenker appears in a process command line — near-zero FP; (3) a known-malicious payload hash is written to disk; (4) DNS resolution to the threat actor's fake Go ecosystem domains or its three named attacker Slack workspaces; (5) a CI/CD runner spawns terraform/go as a pivot toward production cloud credentials; (6) a non-Slack process polls api.slack.com broadly (medium confidence, DNS-level only); (7) a developer host talks to public blockchain RPC infrastructure with no Web3 business justification (low confidence, high FP, correlation-only).

StepTelemetryHunt Angle
1. Social-engineering lure (fake Web3 recruiter on LinkedIn/Facebook, fake coding-interview task)None (pre-endpoint)Security-awareness training; HR/recruiting-process controls (Section 12, Strategic tier)
2. Victim runs terraform init/apply or go get/go build against the malicious package in the provided repoProcessRollup2, CommandLineQ1, Q5, Q7
3. Activation gate: SHA256(containerName+networkID) == fixed value, or a crafted numeric fieldNone — not visible to EDR (in-memory Terraform variable comparison)Coverage gap (Section 15) — cannot be hunted directly; only its downstream effects (steps 4-8) are observable
4. AES-decrypt embedded file path/payload using the gate hash as key material; unzip archive contentsFile-write telemetry on the decrypted archiveQ6 (hash match on import-resource.sqlite3 / btreex.sql)
5. Execute decrypted code via detached go run .ProcessRollup2 parent-child lineageQ2
6. Second-stage RAT gathers host info; check-in posted to Slack channel frontend-devs in portfolio-devs.slack.comDnsRequest (slack.com), network telemetryQ4 (broad), Q9 (precise, named workspace)
7. Ephemeral keypair generated; shared key derived from two hardcoded threat-actor public keys; all further Slack traffic moves to qa-announcements in portfolio-testers.slack.comDnsRequest (slack.com, recurring)Q4 (broad), Q9 (precise, named workspace)
8. Parallel blockchain C2: read/write Arbitrum Sepolia contract 0xAD02b5cDE693529d3bdA0266299501ad0193036C via setCPubKey; poll every 3s (blockchain) / 10s (Slack)DnsRequest/NetworkConnectIP4 to blockchain RPC infraQ8 (behavioral only)
9. Execute attacker-issued Go or Node.js commands, or self-deleteProcessRollup2 (node/go child processes), file-delete telemetryPartial — downstream child-process hunts only; content of commands is opaque (encrypted)
04

Consolidated IOC Table

All indicators below ship at action detect, not prevent — this pack is single-primary-sourced (Aikido) for the core Graphalgo Terraform/Go indicators. Promote to Prevent only after independent second-source corroboration or a clean 14-day bake in your own tenant (Section 11).

TypeValueConfidenceActionContextExpiry
sha2565f892a5424e88a21a3eb3d7f82ebf04d8ac31cdb19ada25153be4165df977d0fhighdetectimport-resource.sqlite3 — AES-encrypted/zipped payload embedded in both malicious Terraform providers2027-03-24
sha256ab01686d87565250fc4989faddb877d793667b07ec217a61cbd798f5695d62f5highdetectbtreex.sql — ZIP archive masquerading as a SQL file, payload for gogets.dev/btreex2027-03-24
domaingocommunity.iohighdetectThreat-actor-controlled fake Go package-ecosystem site; social-engineering legitimacy prop2027-03-24
domaingogets.devhighdetectThreat-actor-controlled fake Go package-ecosystem site; social-engineering legitimacy prop2027-03-24
domainportfolio-devs.slack.comhighdetectAttacker-controlled Slack workspace, channel frontend-devs — initial check-in C22027-03-24
domainportfolio-testers.slack.comhighdetectAttacker-controlled Slack workspace, channel qa-announcements — post-handshake C22027-03-24
domainmediumstar.slack.commediumhuntHistorical, previously-unreported attacker Slack workspace noted by Aikido2026-12-24
packagegocommunity-io/dockerd (Terraform provider, 222 downloads)highhuntTrojanized Terraform provider, hidden entry point in resource_docker_container_funcs.go2027-03-24
packagekreuzwenker/docker (Terraform provider, 1,449 downloads)highhuntTyposquat of kreuzwerker/docker (56M downloads); same hidden entry point2027-03-24
packagegocommunity.io/orderedbtree (Go module, published 2026-08-11)highhuntRAT embedded in plaintext, no encryption layer2027-03-24
packagegogets.dev/btreex (Go module, published 2026-09-08, commits forged to Nov 2025)highhuntRAT hidden inside btreex.sql; requires a crafted price-integer input to activate2027-03-24
crypto-key302a300506032b656e...d1b526702 (88 hex chars, ed25519 SPKI, full value in Section 10)highenrichThreat-actor public key, shared across this Go RAT and the npm/PyPI Graphalgo samples since April 2026 (first seen in "modern-events")2026-12-24
otherArbitrum Sepolia testnet contract 0xAD02b5cDE693529d3bdA0266299501ad0193036ChighhuntBlockchain dead-drop C2; setCPubKey method, serviceData1/serviceData2 fields, ~3s poll interval2027-03-24

v0.2: the typosquatted Terraform-registry domains (TraderTraitor) and the GHAPPIER/PolinRider IP + trailing byte marker were removed from this table — they are other campaigns' own infrastructure, not Graphalgo's. See Section 2 for the full reasoning.

05

Affected Surface & Telemetry Matrix

SurfaceRequired TelemetryPriorityGap Risk
Developer workstations (Windows/macOS/Linux) running TerraformProcessRollup2/SyntheticProcessRollup2, DnsRequest, PeFileWritten/ZipFileWrittenCriticalLow — standard Falcon sensor coverage
DevOps / platform-engineering workstations with cloud IAM credentials cachedSame as above + cloud provider audit logs (CloudTrail/Azure Activity Log)CriticalMedium — cloud-side correlation requires a SIEM join outside Falcon
CI/CD runners (GitHub Actions self-hosted, GitLab Runner, Jenkins agents)ProcessRollup2 parent-child lineage, NetworkConnectIP4CriticalMedium — ephemeral/containerized runners may not run a persistent sensor
Go module proxy / GOPROXY egress pathDnsRequest, NetworkConnectIP4HighLow
Terraform Registry / private provider mirror egress pathDnsRequest, NetworkConnectIP4HighLow
Slack API traffic (conversations.history polling)DnsRequest only via Falcon; full URL-path visibility requires a TLS-terminating proxy or Slack's own audit logHighHigh — see Coverage Map
Blockchain RPC traffic (Arbitrum Sepolia)DnsRequest/NetworkConnectIP4 only; on-chain call data is opaque to EDRHighHigh — see Coverage Map
In-memory activation-gate comparison (SHA256 of Terraform variables)None available via EDRInformationalHigh — not observable by design
06

ATT&CK Mapping

TacticTechniqueNameObserved Behavior
Resource DevelopmentT1608.001Stage Capabilities: Upload MalwareTrojanized Terraform providers and Go modules published to the HashiCorp Registry and pkg.go.dev
Resource DevelopmentT1585.001Establish Accounts: Social Media AccountsFake Web3 recruiter profiles on LinkedIn/Facebook; fake GitHub organizations (gocommunity-io, gogets-dev) and companion websites
Initial Access / ExecutionT1195.002Supply Chain Compromise: Compromise Software Supply ChainMalicious Terraform providers and Go modules delivered as fake coding-interview dependencies
ExecutionT1204.002User Execution: Malicious FileVictim runs terraform init/apply or go get/build against the trojanized package
Defense EvasionT1036Masqueradingkreuzwenker/docker (1,449 downloads) typosquats the legitimate kreuzwerker/docker provider (56M downloads)
Defense EvasionT1027Obfuscated/Encrypted Files or InformationPayload AES-encrypted, keyed by a runtime-computed SHA256 gate hash; inert until the exact trigger condition is met
Defense EvasionT1140Deobfuscate/Decode Files or InformationMalware AES-decrypts the embedded file path and unzips the archive at runtime
Command and ControlT1102.002Web Service: Bidirectional CommunicationSlack conversations.history polling and Arbitrum Sepolia smart-contract read/write used as dual dead-drop C2 channels
Command and ControlT1071.001Application Layer Protocol: Web ProtocolsHTTPS to api.slack.com and blockchain RPC endpoints carries all C2 traffic
07

Native Audit-Log Hunts

These checks require no Falcon query — they read the developer's own project files and are cheap enough to run fleet-wide via RTR or an MDM/RMM script before or alongside the CQL hunts.

Go dependency audit (Linux/macOS/Windows)

grep -RIn "gocommunity\.io\|gogets\.dev" $(find / -name "go.sum" -o -name "go.mod" 2>/dev/null) 2>/dev/null
# PowerShell equivalent:
Get-ChildItem -Recurse -Include go.sum,go.mod -ErrorAction SilentlyContinue |
  Select-String -Pattern "gocommunity\.io|gogets\.dev"

Terraform lock-file audit

grep -RIn "kreuzwenker\|gocommunity-io" \
  $(find / -name ".terraform.lock.hcl" 2>/dev/null) 2>/dev/null

GitHub organization / vendoring audit

Check whether any internal repo forks, vendors, or references code from the threat-actor-controlled GitHub identities: gocommunity-io, go-pack-tech, kreuzwenker, gogets-dev, victormmpp, markcary3, steveb082, go-community-admin.

Slack workspace visibility — an honest limit

This campaign's Slack C2 uses attacker-owned workspaces (portfolio-devs.slack.com, portfolio-testers.slack.com, mediumstar.slack.com) reachable from any host with outbound HTTPS. There is no native audit-log visibility into this from your own Slack tenant — your Slack admin console cannot see traffic to someone else's workspace. Rely on DNS/proxy/CASB egress logs (Q4, Q9) instead. Your own Slack Enterprise Grid App Manager audit is still worth running as a separate hygiene check, for any bot/app token with a conversations.history or channels:history scope your security team did not provision.

08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.
Q1 · Terraform Provider Plugin Execution From User-Writable Cache Paths
CONF HIGHFP LOWCOST LOW

Looks for: A terraform-provider-* binary executing from a user-writable Terraform plugin cache path (.terraform.d/plugins, AppData\terraform.d\plugins) or downloaded directly from registry.terraform.io -- the exact vector Aikido documents for gocommunity-io/dockerd and kreuzwenker/docker.

// HUNT: Terraform Provider Plugin Execution From User-Writable Cache Paths
// MITRE: T1195.002, T1204.002
// CONF: high
// FP: low
// COST: low
// REQUIRES: ProcessRollup2/SyntheticProcessRollup2 on Windows, Linux and macOS developer + CI hosts
// FALSE POSITIVES: an internal Terraform provider mirror published under the same terraform-provider-* naming convention
// LOOKBACK: 7d (set window in the Falcon time picker, not in-query)
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| FileName = /^terraform-provider-.*$/i
| (CommandLine = *.terraform.d*plugins* or CommandLine = *terraform.d\plugins* or CommandLine = *registry.terraform.io*)
| table([ComputerName, UserName, FileName, ParentBaseFileName, CommandLine, SHA256HashData, @timestamp])
| sort(@timestamp, order=desc)
Q2 · Detached 'go run .' Execution Spawned By a Terraform Provider Process
CONF HIGHFP LOWCOST LOW

Looks for: A terraform-provider-* process spawning 'go' with a 'go run .' command line -- the documented second-stage launch mechanism (detached go run . executing the AES-decrypted Go RAT source).

// HUNT: Detached 'go run .' Execution Spawned By a Terraform Provider Process
// MITRE: T1195.002, T1027, T1140
// CONF: high
// FP: low
// COST: low
// REQUIRES: ProcessRollup2/SyntheticProcessRollup2 with parent-child lineage (ParentBaseFileName)
// FALSE POSITIVES: provider SDK developers legitimately running 'go run .' inside a provider's own source tree -- rare on a compiled, installed provider's parent process
// LOOKBACK: 7d (set window in the Falcon time picker, not in-query)
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName = /^terraform-provider-.*$/i
| (FileName = /^go(\.exe)?$/i or CommandLine = *go run .*)
| table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, SHA256HashData, @timestamp])
| sort(@timestamp, order=desc)
Q3 · DNS Resolution to Fake Go Package-Ecosystem Domains
CONF HIGHFP LOWCOST LOW

Looks for: DNS resolution to the threat actor's two fake Go package-ecosystem domains (gocommunity.io, gogets.dev), stood up to lend legitimacy to the malicious module publications.

// HUNT: DNS Resolution to Fake Go Package-Ecosystem Domains (gocommunity.io / gogets.dev)
// MITRE: T1195.002, T1608.001
// CONF: high
// FP: low
// COST: low
// REQUIRES: DnsRequest telemetry
// FALSE POSITIVES: none expected -- both domains are threat-actor-registered and provide no legitimate service
// LOOKBACK: 7d (set window in the Falcon time picker, not in-query)
#event_simpleName=DnsRequest
| DomainName = /^(www\.)?(gocommunity\.io|gogets\.dev)$/i
| table([ComputerName, UserName, DomainName, ContextBaseFileName, @timestamp])
| sort(@timestamp, order=desc)
Q4 · Non-Slack-Client Process Polling api.slack.com
CONF MEDIUMFP HIGHCOST LOW

Looks for: A process other than a known Slack/browser client resolving slack.com -- a coarse proxy for the malware's bot-token conversations.history check-in and 10-second poll loop. Falcon NG-SIEM cannot see the API path itself (see Coverage Map, Section 15), so this is DNS-level only. FP: legitimate Slack CLI tools and CI notification integrations also resolve slack.com from non-browser processes -- see the in-query TUNING line before alerting.

// HUNT: Non-Slack-Client Process Polling api.slack.com (Bot-Token Check-in Pattern)
// MITRE: T1102.002, T1071.001
// CONF: medium
// FP: high
// COST: low
// REQUIRES: DnsRequest with ContextBaseFileName process attribution
// FALSE POSITIVES: legitimate Slack CLI tools, CI/CD Slack-notification integrations (PagerDuty, GitHub Actions Slack notifiers), embedded browser webviews
// TUNING: exclude known Slack-integration tooling before promoting -- ContextBaseFileName=/^(slack-cli|slack-notify|pagerduty-agent|zapier-agent)(\.exe)?$/i -- and scope to developer/CI host groups only, not the whole fleet
// LOOKBACK: 7d (set window in the Falcon time picker, not in-query)
#event_simpleName=DnsRequest
| DomainName = /^(www\.)?(api\.)?slack\.com$/i
| ContextBaseFileName != /^(chrome|msedge|firefox|safari|slack|outlook|teams)(\.exe)?$/i
| table([ComputerName, UserName, DomainName, ContextBaseFileName, @timestamp])
| sort(@timestamp, order=desc)
Q5 · Typosquat Terraform Provider Execution (kreuzwenker)
CONF HIGHFP LOWCOST LOW

Looks for: Execution of a docker provider binary whose command line references 'kreuzwenker' -- the exact one-character typosquat of the legitimate kreuzwerker/docker provider (56M downloads) that Aikido identified as the delivery vector.

// HUNT: Typosquat Terraform Provider Execution (kreuzwenker vs. legitimate kreuzwerker)
// MITRE: T1195.002, T1036
// CONF: high
// FP: low
// COST: low
// REQUIRES: ProcessRollup2/SyntheticProcessRollup2 with CommandLine visibility
// FALSE POSITIVES: none expected -- 'kreuzwenker' is not a real HashiCorp Registry namespace
// LOOKBACK: 7d (set window in the Falcon time picker, not in-query)
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| FileName = /^terraform-provider-docker.*$/i
| CommandLine = *kreuzwenker*
| table([ComputerName, UserName, FileName, CommandLine, SHA256HashData, @timestamp])
| sort(@timestamp, order=desc)
Q6 · Known-Malicious Payload Archive Written to Disk
CONF HIGHFP LOWCOST LOW

Looks for: A file write matching the exact filename and SHA256 hash of either published payload archive (import-resource.sqlite3 from the Terraform providers, or btreex.sql from gogets.dev/btreex).

// HUNT: Known-Malicious Payload Archive Written to Disk (import-resource.sqlite3 / btreex.sql)
// MITRE: T1027, T1140
// CONF: high
// FP: low
// COST: low
// REQUIRES: PeFileWritten/ZipFileWritten/NewExecutableWritten file-write telemetry with hash
// FALSE POSITIVES: none expected -- exact hash match against published campaign artifacts
// LOOKBACK: 30d (set window in the Falcon time picker, not in-query)
#event_simpleName=/PeFileWritten|ZipFileWritten|NewExecutableWritten/
| (FileName = /^import-resource\.sqlite3$/i or FileName = /^btreex\.sql$/i)
| SHA256HashData = /^(5f892a5424e88a21a3eb3d7f82ebf04d8ac31cdb19ada25153be4165df977d0f|ab01686d87565250fc4989faddb877d793667b07ec217a61cbd798f5695d62f5)$/i
| table([ComputerName, UserName, FileName, SHA256HashData, @timestamp])
| sort(@timestamp, order=desc)
Q7 · CI/CD Runner Process Spawns Terraform or Go Toolchain
CONF MEDIUMFP MEDIUMCOST MEDIUM

Looks for: A CI/CD runner process (GitHub Actions Runner, GitLab Runner, Jenkins agent) spawning terraform or go -- the developer/CI-runner pivot the campaign specifically targets for its direct line to production cloud credentials. Use as a triage pivot alongside Q1/Q2/Q3/Q9, not a standalone alert. FP: CI jobs run terraform/go constantly -- this query is intentionally broad; see the in-query TUNING line before alerting.

// HUNT: CI/CD Runner Process Spawns Terraform or Go Toolchain (Developer/CI-Runner Pivot)
// MITRE: T1195.002, T1204.002
// CONF: medium
// FP: medium
// COST: medium
// REQUIRES: ProcessRollup2/SyntheticProcessRollup2 parent-child lineage on CI-runner hosts
// FALSE POSITIVES: normal 'terraform apply' / 'go build' CI jobs that legitimately reach the public registry, module proxy, or cloud APIs
// TUNING: exclude known-good CI egress (internal Terraform Cloud/Enterprise host, approved GOPROXY mirror) before alerting; scope to hosts tagged ci-runner -- this query is intentionally broad as a pivot, not a standalone detection
// LOOKBACK: 7d (set window in the Falcon time picker, not in-query)
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName = /^(Runner\.Listener|Runner\.Worker|gitlab-runner|jenkins-agent|agent)(\.exe)?$/i
| FileName = /^(terraform|go)(\.exe)?$/i
| table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, TargetProcessId_decimal, @timestamp])
| sort(@timestamp, order=desc)
Q8 · Developer/DevOps Host Resolving Public Blockchain RPC Infrastructure
CONF LOWFP HIGHCOST LOW

Looks for: A behavioral hunt for the blockchain dead-drop C2 pattern Aikido documents (Arbitrum Sepolia testnet contract polled every 3 seconds) -- DNS to common public RPC provider infrastructure from a host with no documented Web3 business need. The specific RPC endpoint used by this campaign was not published, so this is a category-level behavioral signal, not a confirmed IOC. FP: Web3 developers, wallets, and unrelated tooling resolve these domains constantly -- see the in-query TUNING line; correlate with Q1/Q2/Q5/Q6 before escalating.

// HUNT: Developer/DevOps Host Resolving Public Blockchain RPC Infrastructure (Behavioral Dead-Drop C2 Hunt)
// MITRE: T1102.002, T1071.001
// CONF: low
// FP: high
// COST: low
// REQUIRES: DnsRequest telemetry
// FALSE POSITIVES: legitimate Web3/blockchain developers, wallets, trading bots, or CI jobs that talk to public RPC providers for unrelated reasons -- these domains are NOT themselves Graphalgo indicators, they are a generic infrastructure category the vendor describes the malware abusing (blockchain dead-drop C2)
// TUNING: broad by design -- scope to hosts with no documented Web3/blockchain business need and correlate hits with Q1/Q2/Q5/Q6 process indicators before escalating; do not run this as a standalone alert
// LOOKBACK: 7d (set window in the Falcon time picker, not in-query)
#event_simpleName=DnsRequest
| DomainName = /^(.*\.)?(infura\.io|alchemy\.com|ankr\.com|arbitrum\.io)$/i
| table([ComputerName, UserName, DomainName, ContextBaseFileName, @timestamp])
| sort(@timestamp, order=desc)
Q9 · DNS Resolution to Named Graphalgo Attacker Slack Workspaces
CONF HIGHFP LOWCOST LOW

Looks for: DNS resolution to the three specific attacker-controlled Slack workspace subdomains Aikido confirmed (portfolio-devs.slack.com, portfolio-testers.slack.com, mediumstar.slack.com) -- a precise, near-zero-FP complement to Q4's broad slack.com heuristic.

// HUNT: DNS Resolution to Named Graphalgo Attacker Slack Workspaces
// MITRE: T1102.002, T1071.001
// CONF: high
// FP: low
// COST: low
// REQUIRES: DnsRequest telemetry
// FALSE POSITIVES: none expected -- exact match on three specific, named attacker-controlled Slack workspace subdomains (Aikido), not a generic slack.com heuristic. Complements Q4: Q4 is a broad, high-FP catch-all for ANY non-Slack-client process resolving slack.com; this query is a narrow, near-zero-FP match on Graphalgo's OWN three confirmed workspaces
// LOOKBACK: 7d (set window in the Falcon time picker, not in-query)
#event_simpleName=DnsRequest
| DomainName = /^(portfolio-devs|portfolio-testers|mediumstar)\.slack\.com$/i
| table([ComputerName, UserName, DomainName, ContextBaseFileName, @timestamp])
| sort(@timestamp, order=desc)
09

CrowdStrike Custom IOA Recommendations

NamePatternExclusionsDeployment Path
IOA — Terraform Plugin-Cache ExecutionSame as Q1: FileName=terraform-provider-* under a user-writable plugin cache pathInternal provider-mirror path, if it shares the same folder namingCustom IOA, Detect for 14 days, then Block if clean
IOA — Detached go run . From Terraform Provider ParentSame as Q2: ParentBaseFileName=terraform-provider-* spawning go with 'run .'Provider SDK developer build hosts (tag exception)Custom IOA, Detect for 14 days, then Block if clean
IOA — Typosquat Provider Execution (kreuzwenker)Same as Q5: CommandLine contains 'kreuzwenker'None identifiedCustom IOA, Detect — technically zero-FP and a strong Block candidate once your IOC-governance process independently corroborates this single-sourced indicator (Section 2)
Custom IOC — Known-Malicious Payload HashesSHA256HashData match on either published hash (Q6)None identifiedCustom IOC, Detect — single-sourced, hold at Detect per Section 4's governance note
Custom IOC — Fake Go Ecosystem DomainsDomainName match, Q3 domain set (gocommunity.io, gogets.dev)None identifiedCustom IOC blocklist, Detect immediately given no plausible legitimate use
Custom IOC — Named Graphalgo Slack WorkspacesDomainName match, Q9 domain set (portfolio-devs/portfolio-testers/mediumstar.slack.com)None identifiedCustom IOC blocklist, Detect immediately given no plausible legitimate use

Q4, Q7, and Q8 remain investigate-only hunt queries — each carries FP risk medium or higher and is designed as a correlation pivot, not a standalone detection. Do not promote them to Custom IOA/IOC.

10

Machine-Readable IOC Appendix

Falcon IOC Management CSVbulk import
type,value,action,severity,expiration,description,tags
sha256,5f892a5424e88a21a3eb3d7f82ebf04d8ac31cdb19ada25153be4165df977d0f,detect,critical,2027-03-24,Graphalgo Terraform-provider payload archive (import-resource.sqlite3),campaign:Graphalgo
sha256,ab01686d87565250fc4989faddb877d793667b07ec217a61cbd798f5695d62f5,detect,critical,2027-03-24,Graphalgo btreex.sql payload archive (gogets.dev/btreex),campaign:Graphalgo
domain,gocommunity.io,detect,high,2027-03-24,Graphalgo fake Go ecosystem domain,campaign:Graphalgo
domain,gogets.dev,detect,high,2027-03-24,Graphalgo fake Go ecosystem domain,campaign:Graphalgo
domain,portfolio-devs.slack.com,detect,high,2027-03-24,Graphalgo attacker Slack workspace - check-in C2,campaign:Graphalgo
domain,portfolio-testers.slack.com,detect,high,2027-03-24,Graphalgo attacker Slack workspace - post-handshake C2,campaign:Graphalgo
domain,mediumstar.slack.com,hunt,medium,2026-12-24,Graphalgo historical attacker Slack workspace,campaign:Graphalgo
Behavioral Signaturesnot Falcon-importable
# Behavioral signatures (not directly importable as Falcon IOCs)

Threat-actor public key (ed25519 SPKI, shared across Graphalgo npm/PyPI + this Go port, since April 2026):
  302a300506032b656e032100bad013df6eec5d686f4cc8551e0a5c87a0135164bdd1dafb1c75141d1b526702

Terraform-provider activation-gate hash (SHA256 of containerName+networkID, used as AES key material -- NOT a file hash, cannot be hunted directly, see Section 15):
  b9966e3762e9a0d5d263b8cb3cca07294f81af9714d40ddf4628cb85d74e8ad5

Blockchain C2 method + fields (Arbitrum Sepolia testnet):
  contract 0xAD02b5cDE693529d3bdA0266299501ad0193036C
  method   setCPubKey
  fields   serviceData1, serviceData2
  poll     ~3s

Slack C2 polling cadence:
  endpoint  conversations.history (via api.slack.com)
  poll      ~10s
  packet types: Start / Chunk / End (file-transfer framing)

Execution behavior:
  detached "go run ." launched by a terraform-provider-* or Go-module parent process
  self-deletion capability on attacker command
Named Malware / Tooling / Identitiesreference
# Named packages, providers, modules, and identities

Terraform providers (HashiCorp Registry):
  gocommunity-io/dockerd        (222 downloads)
  kreuzwenker/docker            (1,449 downloads -- typosquat of kreuzwerker/docker, 56M downloads)

Go modules:
  gocommunity.io/orderedbtree   (published 2026-08-11)
  gogets.dev/btreex             (published 2026-09-08, commits forged to Nov 2025)

Malicious file path inside both providers:
  /internal/provider/resource_docker_container_funcs.go

Threat-actor GitHub organizations / accounts:
  gocommunity-io   (org)        go-pack-tech     (committed malware)
  gogets-dev       (org)        markcary3        (committed malware)
  kreuzwenker      (committed malware)
  victormmpp       (published dropper repo, forged commits)
  steveb082        (org member)
  go-community-admin (org member)

Related but DISTINCT clusters -- named for context only, NOT Graphalgo, and NOT this pack's IOCs to ship
(their own indicators belong to their own published packs -- see Section 2 for the full reasoning):
  GHAPPIER loader / PolinRider overlap -- via compromised npm package @dforge-core/dforge-mcp (v0.2.21); see PolinRider-Hunt.html
  TraderTraitor / UNC4899 / PUKCHONG / Jade Sleet -- FLATROOF + ROOFDECK (Rust, macOS), weaponized .terraform.lock.hcl; see TraderTraitor-FLATROOF-ROOFDECK-Hunt.html
Dependency & Lock-File Auditrun on dev/CI hosts
# Dependency & lock-file audit one-liners

# Go module references (Linux/macOS)
grep -RIn "gocommunity\.io\|gogets\.dev" $(find / -name "go.sum" -o -name "go.mod" 2>/dev/null) 2>/dev/null

# Terraform lock-file typosquat references (Linux/macOS)
grep -RIn "kreuzwenker\|gocommunity-io" \
  $(find / -name ".terraform.lock.hcl" 2>/dev/null) 2>/dev/null

# Terraform provider cache inventory (Linux/macOS)
find ~/.terraform.d/plugins -maxdepth 4 -iname "terraform-provider-*" 2>/dev/null

# Terraform provider cache inventory (Windows PowerShell)
Get-ChildItem "$env:APPDATA\terraform.d\plugins" -Recurse -Filter "terraform-provider-*.exe" -ErrorAction SilentlyContinue
11

Detection Validation Gates

GateCheck
Telemetry readyConfirm ProcessRollup2/SyntheticProcessRollup2, DnsRequest, and PeFileWritten/ZipFileWritten/NewExecutableWritten are enabled and flowing for the developer and CI-runner host groups before relying on Q1-Q9.
Benign baselineRun Q1, Q3, Q5, Q6, Q9 over a trailing 30-day window first. Expect zero hits in an environment with no exposure; any hit is a priority triage item, not noise to tune away.
Positive testDetonate the published hashes/domains in an isolated lab VM against a test Falcon sensor (or replay the process-lineage pattern with a benign stand-in binary named terraform-provider-test spawning go run .) to confirm Q1/Q2/Q5/Q6 actually fire before promoting to IOA.
Promotion pathQ1, Q2, Q5 → Custom IOA after a 14-day false-positive-free bake in Detect mode. Q6 → Custom IOC (hash) at Detect, held per the single-source governance note in Section 4. Q3, Q9 → Custom IOC domain blocklist at Detect immediately (no plausible legitimate use). Q4, Q7, Q8 stay Investigate-only.
12

Hardening — Tiered & Deployable

Immediate — this week
  • Lock Terraform provider installation to a vetted source. Deploy a provider_installation block in the CLI configuration file (.terraformrc / terraform.rc) on every developer and CI host, restricting installation to an internal filesystem/network mirror and excluding direct registry.terraform.io access for unvetted namespaces. MITRE M1033 (Limit Software Installation) + M1051 (Update Software). Authority: HashiCorp Terraform CLI Configuration documentation (developer.hashicorp.com/terraform/cli/config/config-file) — ⚠ best-practice, no formal CIS/DISA benchmark item exists yet for Terraform CLI. See Playbook A (Section 13).
  • Block network egress to the confirmed C2 and typosquat infrastructure in Section 4/10 at the firewall/proxy and as Falcon Custom IOCs. MITRE M1037 (Filter Network Traffic). Authority: CIS Controls v8, Control 9 (network/DNS filtering) & Control 13 (network monitoring). Verify: attempt DNS resolution to one of the blocked domains from a test host — expect NXDOMAIN/block and an alert.
  • Enforce dependency-integrity checks in CI: run terraform init -lockfile=readonly so any drift from .terraform.lock.hcl fails the build, and keep Go's checksum database enabled (GOSUMDB must not be off, GOFLAGS=-mod=readonly). MITRE M1045 (Code Signing) + M1051 (Update Software). Authority: HashiCorp dependency lock-file documentation; Go module authentication docs (go.dev/ref/mod#authenticating). Verify: go env GOSUMDB returns sum.golang.org, not off; a modified lock file causes terraform init -lockfile=readonly to fail.
Near term — 1-4 weeks
  • Deploy execution control (WDAC/AppLocker on Windows, Gatekeeper policy on macOS, AppArmor/SELinux mandatory access control on Linux) requiring known-good publishers or path allowlisting for go, terraform, and terraform-provider-* binaries outside package-manager-managed paths. MITRE M1038 (Execution Prevention) + M1045 (Code Signing). Authority: CIS Microsoft Windows 11 Benchmark (AppLocker/WDAC sections) for Windows; CIS Apple macOS Benchmark (Gatekeeper) for macOS; CIS Distribution Benchmark (mandatory access control) for Linux. See Playbook C (Section 13).
  • Restrict outbound Slack API and blockchain-RPC access from developer/CI hosts to sanctioned SaaS endpoints via egress proxy allowlisting; require Slack Enterprise Grid App Manager approval for any bot token with history-read scopes. MITRE M1021 (Restrict Web-Based Content) + M1031 (Network Intrusion Prevention). Authority: CIS Controls v8 Control 9; Slack's own App Manager / approved-apps administration guidance (vendor). Verify: a non-approved outbound HTTPS connection to api.slack.com from a dev host is blocked and logged by the proxy.
  • Rotate and scope down credentials on any host where a flagged package was ever installed: GitHub/GitLab tokens, npm/PyPI/Go publish tokens, cloud provider credentials, SSH keys — prioritize cloud/IaC credentials on Terraform-vector hosts. MITRE M1026 (Privileged Account Management). Authority: vendor incident-response guidance (Aikido advisory) and this pack's own Containment Runbook (Section 14). Verify: token-issuance audit log shows a rotation timestamp after the exposure window closes.
Strategic — 1-3 months
  • Stand up a private Terraform provider registry / internal Go module proxy (Terraform Enterprise private registry, Artifactory, JFrog, or Athens) as the only sanctioned source, gated by a policy-as-code check (Sentinel/OPA) that blocks terraform plan/apply against any non-mirrored provider source. MITRE M1033 (Limit Software Installation) + M1016 (Vulnerability Scanning). Authority: HashiCorp Terraform Enterprise / Sentinel documentation; NIST SP 800-218 (Secure Software Development Framework) practice PW.4. Verify: a terraform init referencing registry.terraform.io directly is rejected by the policy check.
  • Extend software-composition-analysis / SBOM tooling to Terraform providers and Go modules, not just npm/PyPI — the vendor's own advisory notes Terraform Registry coverage is a known gap even in commercial SCA tooling as of this report. MITRE M1016 (Vulnerability Scanning). Authority: NIST SP 800-218 SSDF; CISA/NSA joint guidance on securing the software supply chain. Verify: SBOM/SCA inventory includes Terraform provider sources and their SHA256 checksums, not only language-package-manager dependencies.
  • Security-awareness training covering the DPRK fake-recruiter / fake-coding-interview lure pattern for engineering and DevOps staff, with a documented, low-friction reporting channel. MITRE M1017 (User Training). Authority: general CISA/FBI/Treasury public guidance on DPRK IT-worker and developer-targeting fraud schemes — ⚠ best-practice, no formal benchmark item for this specific control. Verify: LMS completion tracking; a tabletop walkthrough conducted within the quarter.
13

Deployable Playbooks

Playbook A — Terraform CLI Provider-Installation Lockdown

# ~/.terraformrc (Linux/macOS) or %APPDATA%\terraform.rc (Windows)
# Restrict provider installation to an internal mirror; block direct registry.terraform.io
# fetches for anything not explicitly excluded. Verified syntax: developer.hashicorp.com/
# terraform/cli/config/config-file

provider_installation {
  network_mirror {
    url = "https://terraform-mirror.internal.example.com/"
  }
  direct {
    exclude = ["registry.terraform.io/*/*"]
  }
}

Prerequisites: An internal Terraform provider mirror (filesystem_mirror or network_mirror endpoint) deployed and reachable; an inventory of currently-used providers pre-loaded into the mirror so existing builds do not break on rollout.
Reboot required: No.
Rollback: Remove or comment out the provider_installation block (or restore the previous .terraformrc/terraform.rc backup); the next `terraform init` reverts immediately to default direct-registry installation.

Playbook B — Falcon Custom IOC Bulk Import

# Falcon IOC Management -- bulk import via API (requires an API client with iocs:write scope)
# The CSV payload is the grab-csv block in Section 10; convert to Falcon's JSON indicator
# schema before POSTing, or use the IOC Manager console's CSV import.

curl -s -X POST "https://api.crowdstrike.com/iocs/entities/indicators/v1" \
  -H "Authorization: Bearer $FALCON_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "indicators": [
      {
        "type": "sha256",
        "value": "5f892a5424e88a21a3eb3d7f82ebf04d8ac31cdb19ada25153be4165df977d0f",
        "action": "detect",
        "severity": "critical",
        "platforms": ["windows", "linux", "mac"],
        "description": "Graphalgo Terraform-provider payload archive (import-resource.sqlite3)"
      }
    ]
  }'

Prerequisites: Falcon IOC Management enabled for the tenant; an API client credential scoped to iocs:write, or console access with the IOC Manager role.
Reboot required: No.
Rollback: Delete the imported indicator entries via IOC Management (console) or `DELETE /iocs/entities/indicators/v1` (API); does not touch endpoint state and takes effect immediately.

Playbook C — Windows Execution-Control Rule (AppLocker, Audit-First)

# Windows -- AppLocker path-rule sketch (Audit mode first; promote to Enforce after a bake period)
# Deny execution of terraform-provider-* / go binaries from user-writable roots; allow only
# from managed installation paths.

New-AppLockerPolicy -XMLPolicy (
@"
<AppLockerPolicy Version="1">
  <RuleCollection Type="Exe" EnforcementMode="AuditOnly">
    <FilePathRule Id="9c4c2f4e-0001-4a3a-9c1a-000000000001" Name="Deny terraform-provider-* from user-writable roots"
                  Description="Graphalgo hardening - Section 13 Playbook C" UserOrGroupSid="S-1-1-0" Action="Deny">
      <Conditions>
        <FilePathCondition Path="%LOCALAPPDATA%\*terraform-provider-*.exe" />
      </Conditions>
    </FilePathRule>
    <FilePathRule Id="9c4c2f4e-0001-4a3a-9c1a-000000000002" Name="Deny go.exe from Temp/Downloads"
                  Description="Graphalgo hardening - Section 13 Playbook C" UserOrGroupSid="S-1-1-0" Action="Deny">
      <Conditions>
        <FilePathCondition Path="%TEMP%\go.exe" />
      </Conditions>
    </FilePathRule>
  </RuleCollection>
</AppLockerPolicy>
"@) | Set-AppLockerPolicy -Merge
gpupdate /force

Prerequisites: AppLocker's Application Identity service running and the GPO already in Audit mode on the target ring; a baseline capture of legitimate signed Terraform/Go binary install paths so the deny rules do not need to also cover them.
Reboot required: No reboot; the Application Identity service may need a one-time restart if this is its first AppLocker deployment on the host (`Restart-Service AppIDSvc`), and `gpupdate /force` applies the policy without a reboot.
Rollback: Remove the two FilePathRule entries (or revert the RuleCollection to AuditOnly / unlinked) and run `gpupdate /force`; no endpoint state changes are made by the policy itself, only future execution attempts are affected.

14

Containment Runbook

PhaseActionsOwnerEvidence
1. Isolate (0-1 hr)Network-contain the host in Falcon (Network Containment). Capture an RTR triage package (process list, network connections, recently written files) before isolation completes. Disable any Slack bot/app tokens tied to the affected workspace if it is your own tenant. Do not assume killing the visible process ends attacker reachability — per Aikido, C2 channels (Slack, blockchain) can remain reachable independent of the original package.IR lead / SOC L2Falcon RTR triage export, network-containment ticket ID + timestamp
2. Eradicate (1-24 hr)Rotate every credential that touched the host: GitHub/GitLab tokens, npm/PyPI/Go publish tokens, cloud provider credentials, SSH keys — prioritize cloud/IaC credentials on Terraform-vector hosts. Remove the malicious package/provider/module from all repos and local caches. Hunt for the same file hashes/domains fleet-wide (Q3, Q6, Q9). Review recent Terraform applies, GitHub Actions runs, and package publishes made from the host's credentials during the exposure window.IR lead + platform/DevOps engineeringCredential-rotation log, repo diff/audit export, CI run-history export
3. Recover (24-72 hr)Reimage the host — package removal alone is insufficient because the decrypted second stage runs via a detached `go run .` independent of the file on disk. Reprovision from a known-good image. Re-enable network access only after Playbook A (provider-installation lockdown) is enforced on the rebuilt host. Confirm Q1-Q9 return clean for 7 consecutive days before closing the incident.Endpoint engineering + IR leadReimage ticket, 7-day clean hunt-query export, IR lead sign-off
15

Detection Coverage Map

Technique / BehaviorCQLIOACoverage
Package/provider publish-side compromise (T1195.002, T1608.001)——GAP — Falcon has no visibility into the HashiCorp Registry or GitHub publish-side activity; this is a pre-endpoint supply-chain event
Provider/module install & execution (T1204.002)Q1, Q5, Q7IOA-1, IOA-3Good — standard process telemetry, low FP
Activation-gate comparison (SHA256 of Terraform variables / crafted input)——GAP — an in-memory value comparison inside the provider/module process; not observable by EDR, and the vendor notes this is a deliberate anti-analysis design choice
AES decrypt + unzip + detached execution (T1027, T1140)Q2, Q6IOA-2, Custom IOC (hash)Good — process lineage and exact hash match both fire independent of the encryption
Slack C2 check-in and polling (T1102.002, T1071.001)Q4—Partial — DNS-level only; Falcon NG-SIEM cannot see the conversations.history API path itself, which requires a TLS-terminating proxy or Slack's own audit log to confirm
Blockchain dead-drop C2 (T1102.002)Q8—GAP / Partial — behavioral only, high FP; on-chain call data (serviceData1/serviceData2 contents) is opaque to EDR and requires blockchain-analytics tooling or RPC-provider logs for real confirmation
Typosquat provider execution (T1036)Q5IOA-3Good — exact string match, near-zero FP
Named attacker Slack workspaces (T1102.002)Q9Custom IOC (domain)Good — exact domain match on 3 confirmed workspaces, near-zero FP; complements Q4's broader Partial coverage for unknown/future workspaces
Developer/CI-runner pivot to cloud credentialsQ7—Partial — process-level pivot only; confirming actual cloud-credential misuse requires joining against CloudTrail/Azure Activity Log outside Falcon
Self-deletion / anti-forensics——GAP — no dedicated query; only retrospective RTR triage captured before containment (Section 14, Phase 1) recovers this evidence

Validation gates (Section 11) apply to every row above marked Good or Partial before promotion to Prevent/Block.

16

Hunt Summary Ticket

TITLE:      Hunt for Graphalgo Terraform/Go Supply-Chain RAT (DPRK-linked)
SEVERITY:   High (targeted, low-volume, direct cloud-credential exposure risk)
SCOPE:      Developer workstations (Win/Mac/Linux) running Terraform or Go; CI/CD runners
HYPOTHESIS: A developer or CI host executed a trojanized Terraform provider (gocommunity-io/dockerd,
            kreuzwenker/docker) or Go module (gocommunity.io/orderedbtree, gogets.dev/btreex),
            launching a Go RAT with dual Slack/blockchain C2.
QUERIES:    Q1-Q9 (Section 8) -- Q1/Q2/Q5/Q6/Q9 highest confidence; Q4/Q7/Q8 investigate-only
DO FIRST:   Run Q1, Q3, Q5, Q6, Q9 fleet-wide over 30d. Any hit = isolate immediately (Section 14).
FINDINGS:   <populate per engagement>
GAPS:       Activation-gate comparison, blockchain call-data content, and Slack API path are not
            observable via Falcon (Section 15) -- do not certify "no activity" from CQL results alone.
ACTIONS:    Deploy Playbook A (provider-installation lockdown) before closing out a clean sweep.
OWNER:      HuntPack
VERSION:    v0.2 (Draft) -- 2026-09-24
17

Changelog

v0.22026-09-24De-duplication revision (gate 4e, check_coverage.py --check-pack). Removed 4 typosquatted Terraform-registry domains that mechanically collided with the published TraderTraitor-FLATROOF-ROOFDECK-Hunt.html pack, and removed the GHAPPIER/PolinRider IP + trailing byte marker on the same reasoning (that cluster's own infrastructure, not Graphalgo's). Rewrote Q9 around a Graphalgo-owned indicator set (named attacker Slack workspaces) instead of deleting it. Updated IOC table, IOC quick-copy grid, ATT&CK mapping, Section 7 audit one-liners, Section 9 Custom IOA/IOC recommendations, and Section 15 coverage map to match. Query count unchanged at 9; all IDs/anchors unchanged.
v0.12026-09-24Initial draft. Full pipeline run: web-hunter-v2 → threat-hunter-v2 → crowdstrike-logscale-v3 → alert-builder-v2 → threat-hardening-v2 → review-v2. 9 CQL hunt queries, 4 IOC quick-copy blocks, 3-tier hardening with 3 deployable playbooks, phased containment runbook. 4 source snapshots saved and mechanically traced.
18

References

TierSourceUsed ForAccess Date
1Aikido Security — Graphalgo campaign spreads to Terraform providers and Go ModulesPrimary technical disclosure — package names, hashes, C2 mechanics, GitHub pivots2026-09-24
2The Hacker News — Attackers Use Malicious Terraform Providers to Deliver Go Malware via HashiCorp RegistryCorroboration of package/download-count figures; narrative context on the related GHAPPIER/PolinRider overlap (CloudSEK) -- that cluster's own IOCs are not shipped here, see PolinRider-Hunt.html2026-09-24
1ReversingLabs — Inside the 'graphalgo' fake crypto developer recruitment campaignOriginal DPRK/Lazarus attribution and campaign background2026-09-24
1SentinelOne — TraderTraitor Backdoors Resurface on Victim With No Crypto TiesNarrative context only -- Terraform Registry abuse as a broader emerging DPRK TTP; that cluster's own IOCs are not shipped here, see TraderTraitor-FLATROOF-ROOFDECK-Hunt.html2026-09-24
refMITRE ATT&CKTechnique and mitigation (M-number) citations, Sections 6 & 122026-09-24
refHashiCorp — Terraform CLI Configurationprovider_installation block syntax, Playbook A (Section 13)2026-09-24

Generated 2026-09-24 · HuntPack v0.2 (Draft) · Graphalgo Terraform & Go Supply-Chain Hunt