Security1 publisher2 min readPublished
A DPRK-linked package campaign has started publishing to HashiCorp's Terraform Registry
Aikido found the Graphalgo implant inside two Terraform providers and two Go modules. The Go build polls a hard-coded testnet contract every three seconds and keeps a Slack bot channel open as its second route.
The Watch · Security desk

What happened
- Aikido disclosed Go malware shipped inside two Terraform providers and two Go modules, the first use of the HashiCorp registry as a distribution vector for malicious payloads.
- The four packages are gocommunity-io/dockerd at 222 downloads, kreuzwenker/docker at 1,449, plus gocommunity.io/orderedbtree and gogets.dev/btreex.
- The implant overlaps with Graphalgo, a campaign ReversingLabs first documented in February and attributed to North Korean threat actors.
- The Go build polls a hard-coded contract address on the Arbitrum Sepolia testnet every three seconds and executes what comes back as either Go or JavaScript code.
- In the same week, Checkmarx, JFrog and SafeDep flagged eleven npm packages delivering the same malware, among them indexed-btree, crypto-hasher and graphlib-js.
Compiled by The WatchSomething wrong?How this is made
Why it matters
- capability Operators running the fake-recruiter lure can now reach infrastructure engineers who never install an npm or PyPI package, through the provider registry their Terraform configurations already pull from.
- decision Download counts are not a triage signal in this campaign: JFrog says the npm counts were manufactured by a farm of GitHub Actions workers, so the 1,671 provider downloads bound nothing about victims.
- contradiction JFrog's account of the npm packages names the Ethereum Sepolia testnet and Aikido's account of the Go port names Arbitrum Sepolia, so a blocklist built from one chain's RPC endpoints will miss traffic to the other.
- constraint SafeDep recovered the implant but not the code delivered after it, so anyone with a hit has to reconstruct operator activity from their own Slack API and testnet RPC logs.
The entry point is a fake job offer. Developers are approached on LinkedIn and Facebook, or through job postings on forums, by people claiming to work for Web3 companies that do not exist, and the coding exercise they are handed sits in a benign GitHub repository that imports the malicious behaviour as a dependency [4]. In the earlier cases that dependency came from npm or PyPI [4]. Now the same funnel can deliver through a Terraform provider [1].
On first contact the Go build collects hardware attributes, operating system, hostname, and whether the node is available on the infected system, then sends that to an attacker-controlled Slack channel over the API [13]. "Following the check-in call, the malware generates an ephemeral public-private key pair," security researcher Oliver Smith said [14]. The key is then combined with two operator public keys. "The shared key allows the malware to communicate with infected clients using shared channels without exposing C2 communications or leaking messages between infected hosts," Smith said [15].
Both channels run on fixed intervals. The blockchain side polls a hard-coded contract address every three seconds [16], which is 28,800 requests a day from each infected host; the Slack side polls the conversations.history endpoint every ten seconds [9], another 8,640 [2]. Slack traffic is typed: a Start packet opens a file transfer, Chunk packets carry content, an End packet joins them [9]. That design costs the operator throughput. "The threat actor's ability to issue commands is bottlenecked because all clients consume all messages and no-op when they fail to decrypt messages intended for other clients," Smith said [17]. He also called it "a notably sophisticated implementation of a blockchain dead drop that integrates bidirectional communication with minimal risk of information leakage or disruption" [18].
Execution is gated. In some of the npm packages the malware runs only when a specific cryptographic operation is performed [6]. JFrog said the payload "decrypts only when the victim solves a linear system with one specific matrix" [7]. SafeDep described the second route: "The blockchain path also decrypts remote data, writes subwatcher, and starts it with Node.js" [10]. Commands arriving over the contract are executed as Go or JavaScript [16]. The payload is encrypted with asymmetric cryptography and its functions are not known [8].
Aikido said the Go port shares its blockchain and Slack infrastructure with the npm version, using blockchain dead drops and a Slack bot token as dual command channels [12]. For anyone looking through their own logs, that shared infrastructure is the practical link between an npm finding and a Terraform one.
What to watch
- Whether HashiCorp pulls the two providers and publishes real download telemetry for them.
- Whether the same Go port turns up in a provider namespace that imitates an established vendor rather than a generic one.
- Whether any researcher recovers the second-stage code delivered over Slack or the contract, which would establish what operators actually ran.