Feb 10, 2026·6 min read·164 visits
Notepad++ versions before 8.8.9 failed to verify the digital signature of updates downloaded via the generic WinGUp updater. Attackers compromised the update server, swapping the legitimate installer for the 'Chrysalis' backdoor. Update immediately.
For years, Notepad++ has been the Swiss Army knife of developers—lightweight, reliable, and omnipresent. But in mid-2025, it became a Trojan Horse. CVE-2025-15556 reveals a catastrophic failure in the updater mechanism (WinGUp) where binary integrity checks were non-existent. This allowed the Lotus Blossom APT to compromise the official hosting infrastructure and serve a malicious backdoor disguised as a standard update, turning developer workstations into beachheads for espionage.
If you are reading this, there is a statistically significant chance you have Notepad++ installed. It's the 'Hello World' of developer tools—installed on millions of machines, often with administrative privileges, and trusted implicitly by firewall rules and users alike. That trust is exactly what makes it the perfect target for a supply chain attack.
Here is the grim reality: for a long time, the update mechanism for this ubiquitous tool was essentially operating on the honor system. The component responsible for fetching updates, GUP.exe (WinGUp), is a generic updater used by several open-source projects. Its job is simple: download an XML file, parse the URL for the new installer, download the binary, and run it.
But simplicity is the enemy of security. While the connection might have been over HTTPS (protecting the pipe), the payload itself was never interrogated. The updater didn't check who signed the binary, or if it was signed at all. It just grabbed whatever the server offered and executed it. When the Lotus Blossom APT compromised the hosting provider for notepad-plus-plus.org, they didn't need to break encryption or find a 0-day in Windows. They just had to swap a file.
The vulnerability is classified as CWE-494: Download of Code Without Integrity Check, but let's call it what it is: Blind Faith. The architecture of the flaw is a classic case of confusing transport security with content security.
The logic flow of the vulnerable GUP.exe was effectively:
update.xml.<Location> tag.HTTP GET the executable.ShellExecute the executable.There was no step 3.5. There was no hash check against a trusted manifest (because the manifest itself wasn't signed), and there was no Authenticode signature verification on the downloaded binary. This meant that if an attacker could control the server response—either via Man-in-the-Middle (MitM) or, in this case, by compromising the server directly—they owned the client.
This is distinct from a buffer overflow or a use-after-free. The code worked exactly as written; it was just written with the naive assumption that the server is immutable and benevolent. In the modern threat landscape, assuming your infrastructure is unhackable is a fatal architectural error.
The fix required a fundamental change in how WinGUp handles trust. It wasn't enough to just check if a file is signed; anyone can sign a binary with a self-signed cert. The updater needed to verify that the binary was signed specifically by the Notepad++ developers.
In the patch (Commit ce0037549995ed0396cc363544d14b3425614fdb), the Generic Updater was overhauled to utilize the Windows WinVerifyTrust API. It introduced a suite of new command-line flags to enforce strict pinning.
Here is the logic added to the main Notepad++ application (Commit bcf2aa68ef414338d717e20e059459570ed6c5ab) to invoke the hardened updater:
// The new 'SecurityGuard' class retrieves the expected signer details
SecurityGuard sgd;
// Constructing the command line for GUP.exe
// Before: effectively just "-update"
// After: Paranoid Mode engaged
param += L" -chkCertSig=yes"; // MUST be signed
param += L" -chkCertRevoc"; // Check CRL/OCSP
param += L" -chkCertTrustChain"; // Validate the CA chain
param += L" -chkCertName=" + sgd.signer_display_name(); // Pin the Subject Name
param += L" -chkCertAuthorityKeyId=" + sgd.authority_key_id(); // Pin the Issuer> [!NOTE]
> Certificate Pinning is Key:
> Simply checking WinVerifyTrust isn't enough. An attacker could buy a valid cert from a shady CA. The parameters -chkCertName and -chkCertAuthorityKeyId ensure that the certificate actually belongs to the Notepad++ project, effectively killing the attack path unless the attacker steals the private signing key itself.
This wasn't a theoretical research paper; this was an active campaign. The Lotus Blossom APT (a suspected state-sponsored group) managed to compromise the shared hosting provider used by Notepad++. They didn't hit everyone; they used a surgical redirection script to target specific IP ranges, keeping the noise low.
When a victim opened Notepad++ and the "Update Available" dialog popped up, they clicked "Yes" because they are good security citizens who patch their software. The updater downloaded what looked like npp.8.6.9.Installer.x64.exe.
The Payload: Chrysalis The dropped binary wasn't Notepad++. It was a sophisticated loader chain designed to evade EDR:
BluetoothService.exe. This was actually a legitimate, signed binary from Bitdefender (Submission Wizard).log.dll placed in the same folder by the attacker.log.dll used a custom linear congruential generator (magic constants 0x19660D and 0x3C6EF35F) to decrypt shellcode in memory, launching the Chrysalis backdoor.This technique is devious because the process initiating the network connection is a signed security tool (the hijacked Bitdefender binary), often whitelisted by other security products.
The impact of CVE-2025-15556 is effectively Arbitrary Code Execution (ACE) with the privileges of the user running Notepad++. Since developers often run their editors as Administrator (to edit config files, hosts files, etc.), this frequently translates to full system compromise.
The Chrysalis backdoor provided the attackers with:
Because this is a supply chain attack, the "Patient Zero" is often inside the secure zone. You didn't click a phishing link; you updated your trusted tools. This bypasses the human layer of defense entirely.
The remediation is straightforward but urgent: Update to Notepad++ 8.8.9 or later. This version includes the patched GUP.exe and the necessary logic to enforce signature verification.
For enterprise environments, detection is critical since the attack happened before the patch was available. Security teams should hunt for:
BluetoothService.exe running outside of a Bitdefender directory.log.dll appearing in temp folders or alongside the Notepad++ executable.GUP.exe or notepad++.exe.Going forward, the Notepad++ team has also implemented checks for the XML metadata itself (XMLDSig) in version 8.9.2, closing the loop on the manifest manipulation vector. The lesson here is painful but clear: If you are downloading code from the internet, cryptography is not an optional feature—it is a requirement.
CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Notepad++ Don Ho | < 8.8.9 | 8.8.9 |
| Attribute | Detail |
|---|---|
| CWE | CWE-494 |
| CVSS v4.0 | 7.7 (High) |
| Attack Vector | Network (Man-in-the-Middle / Compromised Server) |
| Impact | Arbitrary Code Execution / Malware Installation |
| EPSS Score | 0.00038 |
| Exploit Status | Active (Lotus Blossom APT) |
The product downloads source code or an executable from a remote location and executes the code without sufficiently verifying the origin and integrity of the code.
A symbolic link directory traversal vulnerability was identified in go-git, a pure Go implementation of the Git specification. This vulnerability allows an attacker to construct a repository that, when checked out or processed, bypasses directory boundaries to write or overwrite arbitrary files on the host filesystem.
CVE-2026-71557 is a path traversal vulnerability in go-git, a pure-Go implementation of Git. In vulnerable versions, the filesystem-backed storage engine fails to validate reference names before mapping them to on-disk paths. An attacker hosting a malicious Git server can advertise references containing directory traversal sequences, such as 'refs/heads/../../config', to write or overwrite files outside the intended reference storage directory.
An information disclosure vulnerability in the Nuxt development server allows adjacent network attackers to retrieve the absolute project root directory and a persistent workspace UUID by querying the unprotected Chrome DevTools workspace endpoint. This occurs when the development server is bound to a network-reachable interface, allowing requests that bypass the header-based security verification checks.
A Regular Expression Denial of Service (ReDoS) vulnerability exists in SvelteKit's content negotiation header parser prior to version 2.70.2. An unauthenticated remote attacker can exploit this vulnerability by sending a crafted Accept header with highly repetitive malformed values. This triggers catastrophic backtracking on the single-threaded Node.js/Bun event loop, leading to CPU exhaustion and full denial of service.
An OS command injection vulnerability exists in the npm package loading component of the jsii-diff CLI tool within the AWS jsii framework. Prior to version 1.131.0, when parsing package specifiers prefixed with `npm:`, the tool concatenated user-controlled inputs directly into a shell execution string via child_process.exec. This allows attackers to execute arbitrary shell commands under the context of the running Node.js process.
CodeIgniter4 versions prior to v4.7.4 contain a protocol-spoofing vulnerability due to improper verification of upstream reverse proxy forwarding headers. Remote, unauthenticated attackers can inject headers like X-Forwarded-Proto to deceive the framework into identifying an insecure HTTP request as a secure HTTPS connection.