Back www.acronis.com Red Heron Exploits Gitea N Day Flaw In Multinational Campaign Exposing New Linux Rootkit
Acronis Threat Research Unit (TRU) uncovered a multinational campaign in which a Chinese-speaking threat actor, tracked as Red Heron, rapidly weaponized CVE-2026-60004 to compromise internet-facing instances of Gitea, a self-hosted source-code management platform. The activity progressed from source-code theft to persistent access, credential collection, and lateral movement.
Author: Subhajeet Singha
Acronis Threat Research Unit (TRU) uncovered a multinational campaign in which a Chinese-speaking threat actor, tracked as Red Heron, rapidly weaponized CVE-2026-60004 to compromise internet-facing instances of Gitea, a self-hosted source-code management platform. The activity progressed from source-code theft to persistent access, credential collection, and lateral movement, including root-level access to a three-node Proxmox cluster.
TRU traced a Linux implant to Red Heron’s exposed staging server, revealing the actor’s exploitation tools, reconnaissance databases, command history, stolen repositories, and malware. This provided rare visibility into the operation, from target selection and vulnerability weaponization to post-exploitation activity.
Red Heron scanned 1,386 Gitea instances across seven countries and maintained a separate dataset of 477 Taiwan-based systems. Targets were classified using Simplified Chinese labels covering defense, elections, energy, aerospace, telecommunications, government, and research. Confirmed compromises affected organizations in Canada, Argentina, Taiwan, the United States, and Sri Lanka.
Within days of the vulnerability’s July 2026 disclosure, Red Heron transformed public proof-of-concept code into an automated framework capable of registering accounts, exploiting vulnerable servers, stealing repositories, and removing selected traces. The campaign demonstrates how quickly n-day vulnerabilities in self-hosted development platforms can expose source code, credentials, secrets, and connected infrastructure.
The staging server also contained JITTERLY, a C++ Linux implant supporting more than 30 post-exploitation commands, including shell execution, file transfer, network tunneling, interactive terminal access, and internal pivoting. Embedded inside it was SIXZUT, a previously undocumented LD_PRELOAD rootkit capable of hiding files, processes, and network connections, preventing the implant from being terminated, and relaunching it if the process is stopped while the binary remains present.
TRU assesses with moderate confidence that Red Heron operates within a PRC-linked context, based on Simplified Chinese operational material, its classification of Taiwan as part of China, and targeting aligned with apparent strategic collection priorities. We have not identified sufficient evidence linking Red Heron to a previously tracked threat group.
During routine threat hunting, Acronis Threat Research Unit (TRU) identified a Linux implant, which we track as JITTERLY, and traced it to an exposed staging server operated by a threat actor we track as Red Heron. Discovered on August 4, the server contained exploitation tools, targeting data, command history, stolen repositories, and malware, providing rare visibility into the actor’s operations.
A related JITTERLY sample had previously been publicly analyzed and linked to Adaptix C2 , an open-source framework used to control compromised systems during post-exploitation operations. TRU’s investigation connects the implant to Red Heron and reveals that it contains an embedded Linux rootkit, which we track as SIXZUT. The rootkit can conceal files, processes, and network connections, protect JITTERLY from termination, and relaunch it if it is stopped or removed. We identified no public reporting on SIXZUT.
Red Heron weaponized CVE-2026-60004, a critical Gitea remote code execution vulnerability, within days of public proof-of-concept code appearing on GitHub. The actor developed it into an automated framework capable of registering accounts, exploiting vulnerable servers, stealing repositories, and removing selected traces. Red Heron scanned 1,386 Gitea instances across seven countries and maintained structured target databases using Simplified Chinese classifications covering defense, elections, energy, aerospace, telecommunications, government, and research.
Recovered records documented successful compromises in Canada, Argentina, Taiwan, the United States, and Sri Lanka. Observed activity included source-code theft, credential collection, SSH persistence, backdoor deployment, and lateral movement. In one Taiwanese environment, the actor progressed from a vulnerable Gitea server to root-level administrative access across a three-node Proxmox cluster. The same infrastructure was also associated with a separate campaign targeting 18 predominantly Joomla-based websites across 10 countries.
TRU assesses with moderate confidence that Red Heron operates within a PRC-linked context, based on its Simplified Chinese operational material, targeting taxonomy, treatment of Taiwan as part of China, and apparent collection priorities. This research examines the campaign’s rapid n-day weaponization, victim compromises, operator tradecraft, JITTERLY and SIXZUT, and the evidence supporting our assessment.
Anatomy of CVE-2026-60004: exploiting Gitea’s patch workflow
CVE-2026-60004 is a critical remote code execution vulnerability in Gitea, scoring a 9.8 on the CVSS v3.1 scale. It affects all versions from 1.17 through 1.27.0 and was patched in version 1.27.1 on July 27, 2026. The security advisory containing technical details and a working proof-of-concept was published the following day. The vulnerability was reported by security researcher Shai Rod (NightRang3r) .
The vulnerability sits in Gitea's diffpatch endpoint. When processing repository patches, the vulnerable code runs git apply --index --recount --cached --binary inside a bare temporary clone and adds the -3 flag to enable three-way merge fallback on servers running Git 2.32 or newer. An attacker can abuse this by submitting the same crafted patch twice. The first submission places the payload in the index, the second triggers an add/add collision that forces Git's three-way merge path to check the file out to disk, even though the operation was meant to stay index-only. Because the clone is bare, the repository root doubles as $GIT_DIR , so a file written to hooks/post-index-change lands directly in Git's active hook directory and executes as the Gitea service account the time Git touches the index.
While the diffpatch API requires repository write access, Gitea ships with open registration enabled by default. On instances where open registration remains enabled, an outside attacker can complete the exploitation chain by registering an account, creating a repository, submitting the payload, and achieving code execution without requiring pre-existing credentials. From the attacker’s perspective, this removes the need for prior account access on default-configured, internet-facing instances.
Gitea addressed this in version 1.27.1, released on 27 July, by switching the temporary clone from bare to non-bare, which removes the hook installation path because the repository root no longer serves as $GIT_DIR. The full CVE-2026-60004 advisory followed the day.
Timeline: from proof of concept to active exploitation
On July 27, 2026, Gitea shipped version 1.27.1 which patched CVE-2026-60004. The change appears in the release notes as "Fix: git patch apply." The following day, Gitea published the full security advisory alongside a working proof-of-concept. Multiple public PoC repositories started appearing on GitHub almost immediately.
Within days of the advisory going public, the operator cloned a PoC from GitHub ( HORKimhab/CVE-2026-60004 ) and started building on top of it on July 29, 2026. Tooling timestamps pulled from the staging server's .viminfo show the operator iterating through multiple script versions, testing first against local lab infrastructure and then against live targets outside Taiwan.
On August 3, Red Heron launched a batch run against a 50-target Taiwanese subset. Exfiltration results were mixed, with several targets timing out during repo transfers. The following day, exploitation continued with five more victims showing up as timestamped folders in the downloaded_repo/ directory. During this window, the operator also connected over SSH to a compromised Taiwanese NAS on port 45000 and obtained root access.
It was around this same time that Acronis TRU's internal threat hunting flagged the JITTERLY implant. Tracing the sample back led us to the exposed staging server at the open directory, where everything the operator had built, stolen, and logged was exposed without authentication.
Red Heron’s target taxonomy
Upon looking into the operator's target taxonomy and recon framework, we found that Red Heron had built a structured reconnaissance pipeline powered by FOFA, where they scanned 1,386 Gitea instances across seven countries, running 50-thread automated probes from their VPS to identify which targets had open registration.
Every target was then classified using PRC-style intelligence sector categories written entirely in Simplified Chinese: 国防/军工关联 (defense/military), 选举/投票系统 (election/voting systems), 能源企业 (energy), 航天/空间 (aerospace), 电信企业 (telecom), 政府/市政/公共服务 (government/municipal), and so on. Each entry carried a confidence rating (高, 中, or 低) and source tags like critical_infra and notable_public . The 128 targets with open signup were filtered into a prioritized attack list (open_sites.json) , while a separate Taiwan-focused collection of 477 instances was compiled into tw_assets.json .
That second list is interesting because its metadata carries the field "source: Given authorized website", which suggests it was not generated by the operator's own scanning but provided externally. Combined with the exec.sh script that mirrors stolen data off the staging server from a separate machine and the ssh vps command in the bash history confirming access to at least a second server, we believe there is more than one individual behind the Red Heron operation.
Red Heron also targeted election and voting systems, classified under 选举/民主/公民 and 选举/投票系统 in their taxonomy. The attacker was able to gain RCE on servers with names referencing voter dashboards, tagged under public_sector , although data exfiltration could not be confirmed. Beyond the exploitable target list, the broader reconnaissance scan in master_scanned.json also swept across an organization affiliated with a U.S political party, which was classified under 非营利/基金会 and 政府/法院 (government/judiciary) and flagged as notable_public . That one had authentication enabled, so it was not exploitable through the open registration path, but its presence in the scan shows what Red Heron was looking for or were targeting.
Therefore, here are the total set of targets that we found across Red Heron's operational files with some of them containing evidence of confirmed exploitation, which we will look at the sections.
Operator’s tradecraft
The exposed staging server's .bash_history gave us a line-by-line look at how Red Heron operated, from initial setup through active exploitation. What follows is reconstructed directly from that history.
Before Gitea comes Joomla
While analyzing the operator’s .bash_history , we found that before weaponizing the Gitea vulnerability, they were already running a separate campaign. The bash history opens with the operator executing a script called exp.py with a -shell flag against 18 websites across 10 countries. These were not Gitea targets. We confirmed that 17 of the 18 were running Joomla. The --shell flag is notable, as the available evidence is consistent with its use to deploy a backdoor during post-exploitation. The specific vulnerability could not be confirmed because the Joomla exploit source code was not recovered. Although the timing overlaps with several critical Joomla vulnerabilities disclosed during mid-2026, the available evidence is insufficient to determine which vulnerability was exploited.
One of those targets, a famous overseas education consulting firm based out of India, was confirmed still running a vulnerable JCE editor version (2.9.99) at the time of our analysis. We also observed that the operator targeted a US-based IT managed service provider during this campaign. However, we cannot confirm whether this was a legitimate compromise or if the target was operating a honeypot or research infrastructure, so we are withholding the name at this time.
The pivot to Gitea based on the operator’s command line history, started with a single git clone. The operator pulled HORKimhab's public proof-of-concept for CVE-2026-60004 straight from GitHub and began configuring the environment. The setup required repeated correction. They tried python -m venv venv first, forgot the 3 , had to install python3.12-venv because it was not on the VPS, then finally got the virtual environment running and installed requirements.
Their first target was a US-based cybersecurity company. The initial attempt used the wrong script name entirely (gitea_diffpatch_rce_poc.py), followed by a ls to figure out what the actual filename was. Once they found cve-2026-60004.py, they tried three more times against the same target with slightly different usernames and URL formats (abc, ac, trailing slash on, trailing slash off). None of it worked. Whether the target was patched, had registration disabled, or was running a honeypot, we cannot confirm .
Then, we saw the operator re-export GITEA_PASSWORD , confirm it with echo, and move on. This is where the real iteration began. They started forking the original PoC into their own exp.py, testing each modification against a live target using the username dsaopk. The pattern in history is straightforward: vim exp.py, run it, vim exp.py , run it again, repeatedly until it worked. The -k flag for SSL certificate bypass was one of the first things they added.
Once the tool was stable, they started moving to real targets. The progression from 'id' to 'ls' to "cat /etc/issue" on one target shows them going from verifying execution to enumerating the host. That target, whose title includes " Voter Dashboard Git ," would go on to become one of the most heavily targeted instances in the campaign with 14 separate exploitation sessions documented in the poc-results.
Backdoors and persistence
, we discovered that the threat actor had deployed a persistent backdoor on compromised targets, accessible over raw TCP using the authentication key [auth key redacted]. The bash history shows them checking in on it repeatedly via netcat:
echo "[auth key]:id" | nc 48931 echo "[auth key]:ls" | nc 48931
The protocol is simple: key:command piped over a raw TCP connection. Between backdoor check-ins, we saw the operator pivot to exploiting, a famous Argentine quantitative trading firm. They mistyped the domain on the first attempt where they forgot to add the proper domain spelling, corrected it on the second try, and got RCE.
We also noticed the operator mistyped the backdoor auth key at one point ([auth key redacted, mistyped], missing the number 7), which tells us this was being typed manually each time rather than scripted. They then moved to another target with the --dump-fs flag, exfiltrating repositories and database contents directly from the filesystem.
Therefore, based on data retrieved from the threat actor’s arsenal, here are the confirmed targets across five countries that had been stored in the folder of poc-results, although the original names have been redacted for multiple reasons.
A total of eleven targets across five different countries.
Post-exploitation, Exfiltration and Lateral Movement
Post compromise the threat actor used a password cracking tool known as hashcat as Gitea stores user credentials as bcrypt hashes in its database, and the --dump-fs flag in their tooling pulls the entire Gitea data directory including gitea.db.
Further, we also confirm that the threat actor had compromised an Argentine quantitative trading firm classified under 量化/高频交易 in their target taxonomy. The poc-results for this target show the operator ran a systematic enumeration script that probed the server's temp files, authentication configs, syslog, nginx access logs, bash history, Gitea logs, and nginx configuration in sequence. The output ends with WS OK , which we assess indicates that a backdoor was successfully deployed.
What made this target interesting was the second access mechanism was instead of the raw TCP backdoor used on other victims; the operator accessed this one through the Gitea metrics API endpoint:
curl -k 'hxxps://gitea[.]redacted[.]com[.]ar/api/v1/metrics?k=[auth key redacted]&x=id'
Same auth key, different delivery. The k parameter handles authentication, x carries the command. To anyone watching network traffic, this looks like a standard Prometheus metrics query. The operator ran into trouble trying to pass spaces in commands through curl though. We can see them in the history cycling through single quotes, double quotes, URL encoding (ls%20root), and at one point what appear to be smart quotes, likely from copy-pasting out of a messaging app. They eventually gave up on ls /root and went back to single-word commands like id.
Apart from the compromise of the Argentine trading firm, we also found that Red Heron had successfully pulled source code from multiple other victims. The downloaded_repo/ directory on the staging server had timestamped exfiltration folders for five targets.
We found that the exfiltrated data from the Taiwanese manufacturing company was by far the largest. Upon investigation, we identified this target as a Taiwanese industrial automation company . The operator pulled hundreds of repositories from this single host, we found repositories for what appears to be their s urveillance and monitoring product, a SCADA/HMI tool used in industrial control environments, IoT platform integrations, a network sniffer, server configurations, and internal business applications . We also counted over 130 leftover poc-* directories from this host alone, which are repos the exploit auto-creates each time it runs, and since the cleanup clearly did not work here, it gives us a rough count of how many times Red Heron ran the chain against this target. A Qatar-based target also had data successfully pulled, including a learning management platform, an AI chatbot, workflow automation tools, and WordPress plugins. The remaining three targets from the batch run had exploit artifacts present but no actual repository data, likely due to connection timeouts.
Four additional targets had their repositories pulled within the same two-minute window: a Sri Lankan IT consultancy , a Canadian cloud platform , a Qatar-based technology professional's personal server, and a US-hosted Azure instance . The tight timestamps confirm these came from the automated batch run rather than manual exploitation.
Further, we also saw Red Heron move deeper into a Canadian company operating in the renewable energy space. Out of all the targets in this campaign, this one was by far the most extensively compromised, with 22 separate exploitation sessions documented in the poc-results.
The operator did not just steal repositories here. They mapped the entire infrastructure, identified a legitimate employee's account, and pulled down the company's full application stack including their HR system, CRM, authentication service, company intranet, internal reports, and business APIs. Configuration secrets including JWT tokens, internal tokens, and SSH host keys were extracted from the Gitea configuration. A deploy key tied to the company's HCM staging environment was also exposed.
What made this compromise stand out was the persistence observed on the server. The operator planted three SSH key entries corresponding to two unique keys in the server’s authorized_keys file, including entries explicitly named [victim name]-backdoor and root-shell . A reverse shell was also launched back to the operator’s infrastructure. In addition, a [victim name] _repos/ directory on the staging server contained 61 separate database dumps and data pulled through 41 different auto-registered accounts, suggesting that the operator returned to this target repeatedly across multiple sessions.
The operator mapped the internal Docker network, located in the SQLite database, and had full visibility into the container layout. By the time we found this, Red Heron had full control of the company's entire development infrastructure: source code, credentials, secrets, persistent access, and a clear picture of the internal network.
Well, last but not the least important artifact that stood out to us while researching on Red Heron’s targets across Taiwan, is that we saw that while targeting the Taiwanese entity syno02[.]redacted.]com[.]tw, a Synology NAS hosted in Hsinchu, we noticed the operator registered a Gitea account under the username pvenum02. With medium-confidence and based on the logs, we think that the naming is quite deliberate, where pve stood for Proxmox Virtual Environment, enum for enumeration, 02 for second attempt. Their first run under the dsaopk handle returned blank output, so they came back with a dedicated account and a targeted script.
Then, looking into the poc-results, we saw that the operator obtained a Proxmox root authentication ticket (root@pam), giving them full administrative access to the cluster management API. Access escalated rapidly from that point. They created a snippet storage directory on the cluster, uploaded payloads to three separate Proxmox nodes (tapve01, tapve02, tapve03), and then initiated VM backup operations via vzdump across all three, which could facilitate subsequent collection.
For those unfamiliar, vzdump is Proxmox's VM backup utility. The operator was not just looking around,they triggered full virtual machine backups across a three-node cluster as root, which if completed, would give them entire VM disk images, not just Gitea repositories.
In simple terms, Red Heron started with a Gitea RCE on a Synology NAS ended with root-level access to the underlying Proxmox cluster, payload deployment across three nodes, and an attempt to exfiltrate complete virtual machine images. This was by far the deepest lateral movement we observed in the entire campaign.
During routine threat hunting, TRU identified a Linux ELF implant and traced it to Red Heron’s exposed staging server. We track this implant as JITTERLY.
JITTERLY is a C++ ELF implant closely related to a previously reported but unattributed Linux sample with the same core features and capabilities. Its protocol, configuration fields, registration process, and command structure closely match the Linux agent used by the Adaptix C2 framework. However, reverse engineering confirms that JITTERLY was developed in C++ rather than Go. Supporting artifacts include std::unordered_map internals in the session-management code, std::ifstream constructors in the file-exfiltration handler, and error strings associated with libstdc++.
Analysis of JITTERLY’s execution flow identified a central routine coordinating the implant’s initialization, configuration handling, persistence, host profiling, and command-and-control communications. We refer to this routine as implant_main throughout the analysis.
, we saw that the implant daemonizes itself using the standard UNIX double-fork pattern. It calls setsid() to detach from the controlling terminal, forks again, and the parent exits. The child then opens /dev/null (the XOR-decoded path at byte_4F3690) and redirects stdin, stdout, and stderr to it using dup2(), effectively silencing any output. If the file descriptor is greater than 2, it closes it to avoid leaking handles. After that, it calls chdir() to change the working directory.
Following the daemonization, the implant checks if it is running as root via sys_geteuid_wrapper(). If it is, it calls get_self_path() that attempts to resolve the binary's own path through readlink(/proc/self/exe). If that fails, it falls back to a hardcoded string "configd", which we believe is the intended deployment name for blending in with legitimate system processes. The implant then enters a while loop that iterates through an array of file paths at off_4CA5A0 , calling file_contains_string() against each one to check whether it is already installed at any of the known persistence locations.
Beyond the library code, the hardcoded C2 configuration is baked directly into the .data section of the binary. The implant copies 512 bytes from a static blob into a local buffer during initialization. We extracted this blob and found the C2 address sitting in cleartext after a 16-byte null prefix: s2[.]981666[.]xyz[:]8082 . This address gets written into the persistence config during installation, ensuring the implant knows where to call after a reboot.
The implant contains a previously undocumented capability: it decrypts an embedded rootkit, which we track under the alias SIXZUT, using AES-128-CTR at runtime. The encrypted blob sits in the binary's .data section, with its decryption key stored separately at a different offset. We extracted the key 3a1e96289832518bff2feeb868bc61a4 and the 49 KB encrypted blob, decrypted it, and what came out was a fully functional ELF shared library. The rootkit was never downloaded from the C2 as we initially suspected.
Also, apart from the rootkit decryption and analysis that will be covered in the section, we also identified the subroutine responsible for config decryption, related to the JITTERLY implant.
, we also found that when running as root, JITTERLY constructs its installation path by combining /usr/lib/ with its own binary name. For example, if the binary is named configd, the resulting path would be /usr/lib/configd/configd. It then reads /proc/self/exe to check where it is currently running from and compares that against the constructed installation path. If they do not match, meaning the implant has not been installed to its intended location yet; it copies itself there, deletes the original binary, and re-executes the new path with a -nodel flag. That flag tells the new instance to skip the self-deletion step on its startup, preventing an infinite loop of copy-delete-relaunch. This is how the implant migrates itself from wherever the operator initially dropped it into a system directory that looks legitimate. The mechanism by which it is re-executed after a reboot was not established.
For victim and host profiling, JITTERLY resolves the username from the USER and LOGNAME environment variables, falling back to "unknown" when unavailable, and obtains the hostname through gethostname(). To determine the local source address, it uses a common technique: the implant creates a UDP socket, “connects” it to 8.8.8.8:80 without sending application data, and then calls getsockname() to determine which local interface the kernel would use to route traffic to the internet. This allows the implant to determine the host’s outbound IP address without sending an application payload. The username, hostname, IP address, a static identifier, and the binary’s own path are then used to generate a SHA-1 hash that serves as a deterministic beacon ID for identifying the host to the C2.
Then, once the beacon ID is generated and the connection to the C2 is established, JITTERLY sends a registration message containing the full host profile: process name, PID, username, hostname, outbound IP address, root status, operating system version parsed from /etc/os-release, a freshly generated 16-byte AES session key for encrypting subsequent traffic, the configured sleep and jitter values, the current transport mode, and whether the LD_PRELOAD rootkit is active. This gives the operator a complete picture of the compromised host from the very first check-in.
While analyzing, we also found that JITTERLY’s C2 traffic runs over raw TCP sockets with a custom framing protocol on top. Outbound messages pass through a three-stage pipeline: the payload is first serialized into msgpack, then encrypted with AES-128-GCM using the per-session key exchanged during registration and finally prefixed with a 4-byte big-endian length header before going out on the wire. The resulting format looks like: [4-byte BE length] [12-byte GCM nonce] [encrypted msgpack][16-byte GCM tag]
Further, looking into the msgpack layer itself, every message is wrapped in an envelope containing a type field identifying the message kind, beacon_id with the SHA-1 host fingerprint, task_batch_id for grouping related tasks, accepted_task_ids acknowledging that commands were received, and an object array carrying the actual task results. Each entry in that array is its own msgpack map with command_id, job_id, and data. So what goes over the wire is essentially a nested structure: the outer envelope tells the C2 who is talking and what batch this belongs to, and the inner objects carry the actual command output.
, looking into the actual functionalities of this implant, we reversed two key functions. The first one acts as a dispatcher that handles management-level commands like querying rootkit status, uninstalling the implant, and managing persistence entries. Everything else gets passed down to a second function, which contains the full command handler with over 30 supported operations. Here's what we mapped out:
The networking stack supports SOCKS/TCP tunneling, reverse port forwarding, pivot relaying, and interactive PTY terminals with resize support. These capabilities support use of the implant as a pivot or relay within an internal network, allowing the operator to use a compromised host as a foothold for reaching additional systems.
Well last but not the least artifact,we identified JITTERLY as compatible with the Adaptix C2 Gopher protocol. The msgpack serialization, config field names, registration fields, and command ID mappings closely align. One notable difference is that the Adaptix Gopher template specifies AES-256-GCM , while JITTERLY uses AES-128-GCM with 16-byte keys.
This could indicate an older protocol version, a custom build, or a deliberate operator's choice to use a shorter key length. Prior analysis by the researcher dmpdump on a related sample independently identified the Adaptix connection, corroborating our findings.
As we analyzed the JITTERLY implant, we identified a function responsible for decrypting an encrypted blob embedded inside the binary. Upon decryption, the blob was identified as a fully functional LD_PRELOAD rootkit, which we track under the alias SIXZUT. To the best of our knowledge, this is the first public report of SIXZUT being used in this campaign.
The encrypted rootkit sits in the .data section, encrypted with AES-128-CTR using a separate key from the C2 config. Once decrypted, it drops a 49 KB ELF shared library to disk under the name libglthread.so.2, disguised to look like a legitimate OpenGL threading library. The path to this library is then written into the system's LD_PRELOAD configuration, which forces every dynamically linked process on the machine to load it on startup. A lock file at /tmp/.X11-unix.lk, disguised as an X11 display server socket lock, prevents concurrent modification of the rootkit's configuration.
When the rootkit is loaded into a process, its .init_proc constructor runs automatically. The first thing it does is decrypt all its sensitive strings using XOR with key 0x3C, a different key from JITTERLY's 0x9C. It then resolves the original libc functions via dlsym function for all the fifteen functions it hooks that are as follows:
After resolving the hooks, the rootkit decrypts an 18,704-byte embedded configuration blob using its own AES-128 implementation, separate from JITTERLY's configuration routine and before parsing the result, it verifies the decrypted data starts with the magic header ADLGTBL1 and runs a CRC32 integrity check against the full blob. If either check fails, the config is discarded and the rootkit operates without its hiding table. When the checks pass, it parses the config as an array of 584-byte entries, each containing a process or file name to hide (first 64 bytes) and a comma-separated list of IP:port pairs whose network connections should be concealed (remaining 520 bytes). Up to 128 IP:port entries are supported, with wildcard ports, allowed for hiding all connections to a given IP regardless of port.
During analysis of the JITTERLY implant, we identified an encrypted blob containing the ROOTKIT’s embedded configuration. After decrypting the configuration, we observed that it contained no populated process names or network-hiding rules. This may indicate that SIXZUT is distributed as a clean template, although the available evidence does not establish whether the configuration is intended to be populated remotely by Red Heron, remains unconfigured until deployment, or represents an incomplete sample.
, we found that every call to stat, lstat, fstatat, open, fopen, access, readdir, and getdents goes through a filtering function before reaching the real libc. This function runs five separate checks against the incoming path. It looks for exact matches against /etc/ld.so.preload (the file that tells the dynamic linker to load the rootkit) and /tmp/.X11-unix.lk (the persistence lock file). It then checks the path against the configuration-derived hiding table. On top of that, it does substring searches for libglthread.so.2 (the rootkit binary itself) and .ld_aux_cahe (an auxiliary config file used by the rootkit). If any of these five checks hit, the hook either returns ENOENT ("no such file or directory") or silently skips the directory entry.
Then we also found that when a program lists the contents of /proc/ through readdir or getdents, the rootkit reads /proc/ /cmdline for each entry and runs it through the same hiding check. The cmdline content gets its null byte separators replaced with spaces before matching, so the full command line including arguments is checked against the hiding table. Any PID whose command line matches is silently filtered from the directory listing.
Further, we saw one of the more interesting capabilities in SIXZUT is how it handles network hiding. It does not just hook one interface for listing connections. It covers all three paths available on a Linux system.
First, it hooks fopen and intercepts any attempt to read /proc/net/tcp, /proc/net/tcp6, /proc/net/udp, or /proc/net/udp6. Instead of returning the real file, it opens the original through the saved libc pointer, reads it line by line, parses out the local and remote IP:port pairs, checks them against the hiding table, and writes only the non-matching lines into a temporary file that gets returned to the caller. This defeats netstat and any monitoring agent that reads proc files.
, it hooks open/open64 to track which file descriptors point to these proc net files. When read() is called on a tracked fd, the rootkit filters the content the same way. This catches tools that use raw read() instead of fopen().
Finally, it hooks socket to detect AF_NETLINK sockets with NETLINK_INET_DIAG, and hooks recvmsg to filter the netlink responses. This is how ss queries connections directly from the kernel, bypassing proc files entirely. The rootkit parses the netlink message buffer, walks each connection entry, checks the IP:port against the hiding table, and strips matching entries by shifting the remaining data forward with memmove.
Further we saw that SIXZUT also protects the implant from being killed. The hooked kill() reads the target process's /proc/ /cmdline before forwarding any signal. If the process matches the hiding table, the rootkit returns -1 with errno set to ESRCH ("no such process"), so the signal is never delivered. An administrator running kill -9 against the implant's PID gets no error, but the process keeps running.
Well, the last but not the least, the rootkit implant, is we found, during initialization, if the rootkit is running as root, it checks whether the implant binary still exists at its expected install path. If it is missing or not running, the rootkit forks, daemonizes the child (double fork, setsid, redirect to /dev/null), and re-launches the implant with the -nodel flag via execl. Since every process on the system loads the rootkit through /etc/ld.so.preload, killing the implant just means the process launch brings it back.
Attribution and confidence
Based on our analysis, Acronis TRU assesses with moderate confidence that this campaign is attributable to a Chinese-speaking threat actor operating in a PRC-linked operational context, which we track under the alias Red Heron . This assessment is based on multiple lines of analytical evidence, including Chinese-language operational artifacts, PRC-style targeting classifications, victimology, and observed tradecraft, as outlined below.
Simplified Chinese operational artifacts : All reconnaissance databases, target classification taxonomies, and FOFA scan metadata recovered from the staging server were written entirely in Simplified Chinese. Sector categories such as 国防/军工关联 (defense/military), 选举/投票系统 (election/voting systems), 能源企业 (energy), and 航天/空间 (aerospace) follow a structured intelligence collection taxonomy consistent with Chinese collection priorities.
Taiwan classified as domestic territory: Across all operational metadata, Taiwan was consistently designated as country: "CN", region: "TW", treating it as a region within China rather than a separate country. This classification pattern is consistent with operators working within a Mainland Chinese institutional or organizational context.
External tasking indicators : The Taiwan-specific target list (tw_assets.json) containing 477 instances carried the metadata field "source: Given authorized website", suggesting this list was provided externally rather than generated by the operator's own scanning. Combined with the exec.sh script that mirrors stolen data off the staging server via HTTP from a different machine, these details point to a team structure rather than a solo operator.
Tooling and infrastructure patterns : Red Heron relies exclusively on publicly available and open-source tools, including a forked GitHub PoC for CVE-2026-60004, the Adaptix C2 framework for the JITTERLY implant, and FOFA for target reconnaissance.
Building on these converging indicators, including the language artifacts, geopolitical classification patterns, behavioral tradecraft, and structured intelligence-driven targeting, we assess with moderate confidence that this campaign is attributable to a Chinese-speaking operator or group operating in a PRC-linked operational context . We have not identified direct links to any previously tracked APT cluster at this time. We continue to track this activity under the alias Red Heron .
Red Heron demonstrates how quickly threat actors can turn public proof-of-concept code into a scalable n-day exploitation campaign. By combining automated Gitea exploitation with structured target selection, the actor progressed from repository theft to credential collection, persistent access, and lateral movement across victim environments. Its focus on organizations associated with elections, defense, energy, government, and research suggests deliberate collection priorities alongside broader opportunistic scanning.
The exposed staging server provided rare visibility into the operation, including its exploitation framework, reconnaissance data, stolen repositories, and post-exploitation tooling. It also connected Red Heron to JITTERLY and its embedded SIXZUT rootkit, revealing capabilities designed to support covert, persistent access to Linux systems.
This campaign highlights that internet-facing development platforms can provide access not only to source code, but also to credentials, application secrets, deployment infrastructure, and connected systems. Rapid patching, restricted account registration, and close monitoring of self-hosted development environments are therefore essential to preventing an initial repository-server compromise from becoming a broader infrastructure breach.
Mitigation and hunting guidance
The following applies regardless of security vendor. Exploitation of CVE-2026-60004 requires Git 2.32 or newer, an enabled diffpatch route, and a writable and executable temporary filesystem; open registration removes the need for prior credentials but is not itself the vulnerability.
Upgrade Gitea to 1.27.1 or later.
Disable open registration on any instance that does not require it, and restrict the diffpatch API route where it is not in use.
Do not expose Gitea directly to the internet where a VPN or reverse proxy with authentication is practical.
Investigate for prior compromise
Review accounts and repositories created since the advisory was published. Red Heron registered throwaway accounts to reach the vulnerable route.
web and proxy logs for unexpected requests to the diffpatch endpoint, and for requests to /api/v1/metrics carrying unfamiliar query parameters.
Look for Gitea spawning child processes, particularly shells, interpreters or curl. The Gitea service has no legitimate reason to execute a shell.
Check for modification of /etc/ld.so.preload. On most systems this file is absent or static, so any change warrants investigation.
Hunt for the rootkit artefacts libglthread.so.2, .ld_aux_cahe and /tmp/.X11-unix.lk. Note that SIXZUT hides these from userland tooling, so check from a known-good kernel, offline image or EDR telemetry rather than with ls or find on the live host.
Audit authorized_keys on all accounts for entries you cannot attribute, and review outbound connections for reverse shells and beaconing to unfamiliar infrastructure.
Treat any credential, token or SSH host key stored in a compromised Gitea instance as disclosed, and rotate it. Recovered operator data shows database credentials, JWT and internal tokens being collected.
If compromise is confirmed
Rebuild rather than clean. SIXZUT restores itself and protects the implant from termination, so removal on a running host is unreliable.
Assume source code and repository contents were taken, and review them for further embedded secrets before treating the incident as contained.
This threat is detected and blocked by Acronis EDR / XDR:
Indicators of compromise
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
