North Korea’s Contagious Interview Operation Expanded to Five Package Ecosystems. One Staging Server Connects All 1,700 Packages.

North Korea’s Contagious Interview Operation Expanded to Five Package Ecosystems. One Staging Server Connects All 1,700 Packages.
North Korea’s Contagious Interview Operation Expanded to Five Package Ecosystems. One Staging Server Connects All 1,700 Packages.

On March 31, a North Korean threat actor hijacked the npm account of Axios maintainer Jason Saayman and pushed two malicious versions of the HTTP client used by 100 million weekly downloads. The malicious packages were live for roughly two hours before removal. That attack was a single operation against a single target in a single ecosystem.

On April 7, 2026, Socket security researcher Kirill Boychenko published a report showing the same threat actor cluster has been running a parallel operation across five package ecosystems simultaneously. The same staging infrastructure. The same payload delivery pattern. The same fake developer tooling names designed to blend into dependency lists. Twelve confirmed malicious packages published across npm, PyPI, Go Modules, crates.io, and Packagist under a set of coordinated GitHub aliases. Socket’s running tracker for the broader campaign, which has been active since at least 2024, now lists more than 1,700 malicious packages tied to this activity.

The Axios attack was the visible event. This infrastructure is the operation underneath it.

1,700+
Packages Tracked
5
Ecosystems Hit
12
Confirmed Packages
164
Domains Blocked

The threat actor and the campaign

Contagious Interview is a persistent North Korean cyber operation that has been running since at least 2023. Security researchers attribute it to a financially motivated cluster designated UNC1069, which overlaps with threat groups tracked under the names BlueNoroff, Sapphire Sleet, and Stardust Chollima. These are not separate teams. They are different naming conventions applied by different threat intelligence firms to the same operational infrastructure, which originates from North Korea’s intelligence services and funds the Kim regime through cryptocurrency theft and data extortion.

The Security Alliance (SEAL) published a complementary report on April 7 documenting that between February 6 and April 7, 2026, it blocked 164 domains operated by UNC1069. Those domains impersonated legitimate services, predominantly Microsoft Teams and Zoom, and were used in social engineering campaigns conducted across Telegram, LinkedIn, and Slack. The operational pattern is consistent: threat actors build rapport with developers over weeks or months through fake professional identities, then invite targets to a video call that requires downloading malware disguised as a meeting update. Jason Saayman’s account compromise on March 31 followed this exact pattern. The supply chain packages disclosed on April 7 are the passive infrastructure that runs alongside the active social engineering campaigns.

Microsoft’s threat intelligence general manager Sherrod DeGrippo described the operational continuity to The Hacker News: “What we consistently see is ongoing evolution in how financially motivated actors associated with North Korea operate, shifts in tooling, infrastructure, and targeting, but with clear continuity in behavior and intent.”

The packages and what they pretend to be

The April 7 cluster was published under three GitHub aliases: golangorg, aokisasakidev, and aokisasakidev1. Two supporting personas, maxcointech1010 and maxcointech0000, provided additional infrastructure. The packages were designed to impersonate developer tooling that developers routinely install without deep inspection:

npm: dev-log-core, logger-base, logkitx, pino-debugger, debug-fmt, debug-glitz. These names mimic the real npm packages debug, pino-debug, and debug-logfmt, all of which have millions of weekly downloads in the Node.js ecosystem.

PyPI: logutilkit, apachelicense, fluxhttp, license-utils-kit. These mimic license, http, and standard logging utilities.

Go Modules: github.com/golangorg/formstash, github.com/aokisasakidev/mit-license-pkg. The formstash package is mostly a real multipart parser with a malicious helper function appended.

crates.io (Rust): logtrace, which mimics the legitimate libprettylogger crate. This package was tracked as RUSTSEC-2026-0081 and removed by the crates.io security team after Socket’s disclosure.

Packagist (PHP/Composer): golangorg/logkit, mimicking the openlss/func-log package in the PHP ecosystem.

The loader pattern: one infrastructure, five languages

The technical signature of this cluster is the consistency of the staging infrastructure across all five ecosystems. Every package in the cluster follows the same loader workflow regardless of the target language.

Step one: contact the staging endpoint with an HTTP POST. The endpoint is https://apachelicense.vercel.app/getAddress?platform=<platform>, where the platform parameter identifies the operating system. The use of Vercel hosting is deliberate: Vercel domains are broadly trusted by corporate network security tools and rarely flagged in egress filtering rules.

Step two: parse the JSON response, which contains a downloadUrl field. If the URL is a Google Drive sharing link, the loader rewrites it into a direct-download form before fetching. This Google Drive relay pattern is a consistent tradecraft element, as Drive links survive many URL-based threat intelligence blocklists.

Step three: download a ZIP archive. The filename is consistent across the cluster: ecw_update.zip.

Step four: extract the archive into a temp directory. The extraction path is hardcoded and consistent: 410BB449A-72C6-4500-9765-ACD04JBV827V32V. This UUID-format string is specific enough to serve as a reliable indicator of compromise in process monitoring and endpoint detection.

Step five: find and execute the platform-specific payload. On Unix systems, payload names are chosen to mimic legitimate system processes: com.apple.systemevents on macOS and systemd-resolved on Linux. Both names appear in normal system process lists, reducing the likelihood that a developer or sysadmin will flag them during a cursory process review.

The primary payload objective is a RAT-enabled infostealer operation. The malware targets credentials stored in password managers and browsers, cryptocurrency wallet data and private keys, and session tokens for services the developer has authenticated to. Because developers often have access to production credentials, CI/CD tokens, and cloud service API keys, a successful compromise of a developer’s workstation is significantly more valuable to the threat actors than a consumer endpoint.

Where the malicious code hides

The most technically significant aspect of this cluster is where the loader code sits within each package. The threat actors did not rely on install-time execution, which is the most commonly flagged malicious behavior in package registry security scanners. Instead, they embedded the trigger inside methods that look functionally normal for the package’s claimed purpose.

In the PyPI package logutilkit, the malicious trigger sits inside the generic log() method. A call like logutilkit_util.check_for_updates(level) appears inside the standard logging function. Without reading the source, a developer would have no reason to inspect a log call.

In apachelicense and license-utils-kit, the trigger is embedded in a method called find_by_key(). For a package presenting itself as a license lookup library, this is a perfectly plausible helper name. The malicious path calls subprocess.Popen on Windows or a staged loader function on Linux and macOS. The code passes a cursory reading because the method name is appropriate for the package’s stated purpose.

In the Rust crate logtrace, the trigger is inside Logger::trace(i32). A logging crate that exposes a trace method is completely unremarkable. The method body contains the staging endpoint call, the ecw_update.zip download path, and the hardcoded extraction directory.

In the Go module github.com/golangorg/formstash, the package is mostly a real multipart form parser. The malicious functionality is in a helper function called CheckForUpdates(tValue int). This function has no legitimate place in a form parsing library, but its name is generic enough to avoid suspicion in a brief code review.

The strategic implication is that static analysis tools that scan for install hooks or postinstall scripts will not catch this class of package. The trigger executes at runtime, when the malicious function is first called during normal package usage.

The Windows-heavy variant goes further

One package in the cluster stands apart from the standard loader pattern. The PyPI package license-utils-kit includes a Windows-specific execution path that delivers a substantially more capable implant than the standard RAT payload. Socket’s analysis found capabilities consistent with remote shell execution, keystroke logging, browser and wallet data theft, collection of sensitive files by extension and filename pattern, encrypted archiving of collected data, and persistent remote-access deployment.

The distinction matters for incident response prioritization. The standard loader packages in this cluster are initial access tools. license-utils-kit, if executed on a Windows developer workstation, delivers a full post-compromise implant. Organizations whose developers installed this package during the window it was available, and who have not yet identified and remediated the infection, may have an active persistent access point on developer infrastructure.

The second-stage payload hashes documented by Zscaler’s ThreatLabz team provide a verification path for security teams: SHA-256 9a541dffb7fc18dc71dbc8523ec6c3a71c224ffeb518ae3a8d7d16377aebee58 and bb2a89001410fa5a11dea6477d4f5573130261badc67fe952cfad1174c2f0edd, identified from public reporting on the same campaign, correspond to second-stage components from license-utils-kit. A third Python-based RAT payload was separately identified with SHA-256 7c5adef4b5aee7a4aa6e795a86f8b7d601618c3bc003f1326ca57d03ec7d6524.

Registry response and takedown status

Socket reported all identified live packages to the affected registries and submitted takedown requests for the associated GitHub accounts. The crates.io security team removed logtrace and the associated account promptly after disclosure, with the advisory tracked as RUSTSEC-2026-0081. The Go security team blocked the identified malicious Go modules. The npm security team removed the packages associated with the aokisasakidev account. As of the time of Socket’s publication, some packages in the PyPI and Packagist clusters remained live.

Registry-side removal does not protect developers who already installed the affected packages. Any system that executed a malicious package version during its live window should be treated as potentially compromised. The hardcoded extraction directory 410BB449A-72C6-4500-9765-ACD04JBV827V32V in the temp directory is a reliable host-level indicator of compromise. The staging domain apachelicense.vercel.app and the related infrastructure IPs 66.45.225.94, logkit.onrender.com, and logkit-tau.vercel.app are network-level indicators that should be added to egress block lists.

The factory model and what it means for defenders

The Contagious Interview operation is not a team of researchers finding creative new attack surfaces. It is an industrialized production line that takes a working loader pattern and ports it to each new package registry that developers adopt. The same staging infrastructure, the same payload names, the same delivery ZIP, the same extraction path. The operation’s scale, now over 1,700 tracked packages, reflects systematic expansion into whatever channels developers trust, not opportunistic discovery.

This factory model has specific implications for detection. The attack is not novel in execution. The payload and staging patterns are documented and enumerable. What makes it effective is that developers install dozens or hundreds of third-party packages without inspecting their source, and the packages look and function like legitimate tooling until a specific code path executes.

Socket’s recommended detection heuristics for this class of attack are specific and actionable. Treat any utility package as high-risk if it contacts remote infrastructure during normal operation, retrieves a field named downloadUrl from a remote JSON response, rewrites cloud-storage sharing links into direct-download form, downloads archive files into temp directories, decodes remote content before execution, or spawns interpreter processes or binaries from library code. None of these behaviors are legitimate in a logging library, form parser, or license utility. All of them appear in this cluster.

The connection to the Axios compromise and the broader pattern of agent framework vulnerabilities points toward a consistent threat model: developer tooling infrastructure is a higher-value target than consumer endpoints, because developers have privileged access to production systems, cloud credentials, and code signing keys. The Contagious Interview operation is running continuously. The question is not whether it will attempt to reach your dependency tree. It already has.