Apr 6, 2026·6 min read·1 visit
A state-management flaw in PocketMine-MP allows attackers to duplicate items by attacking a disconnecting player during the split-second window before their entity is purged from the server's active lookup table.
PocketMine-MP versions prior to 5.39.2 suffer from a race condition vulnerability in the entity lifecycle management system. A state synchronization delay between entity despawning and lookup table purging permits unauthorized concurrent interaction, leading to arbitrary item duplication.
PocketMine-MP relies on a centralized entity management system to track and update active objects within the game world. The pocketmine/pocketmine-mp package utilizes an internal array within the World class to maintain reference pointers to all active entities. This architecture facilitates rapid, O(1) lookups during high-frequency server ticks.
The vulnerability exists within the state transition logic governing entity destruction and player disconnection. When an entity despawns, the software modifies a boolean state flag (flaggedForDespawn) but defers the actual removal of the object from the active entity array. This deferred garbage collection creates a critical time-of-check to time-of-use (TOCTOU) vulnerability window.
During this transient state, the entity is semantically dead but programmatically accessible. Unvalidated inbound network packets can target the entity's ID, forcing the server to retrieve the "zombie" entity from the lookup table and execute action handlers. Successful exploitation yields unauthorized item duplication, directly compromising application integrity and the specific game economy.
The structural root cause is improper synchronization between an object's lifecycle state and its presence in shared lookup resources (CWE-362). The World object defers the memory management and array unsetting of despawning entities to a dedicated cleanup phase executing on subsequent server ticks. This design minimizes performance overhead during active processing loops.
When a player disconnects, the software immediately serializes and writes their inventory state to persistent storage. Simultaneously, the player's runtime entity receives the flaggedForDespawn = true modification. However, the entity reference remains fully intact within the World->entities lookup table until the tick loop finalizes.
Inbound network packets invoke specific transaction handlers that rely on the World->getEntity($id) method. Prior to version 5.39.2, these handlers retrieved the entity object based on the network packet's specified ID but failed to inspect the flaggedForDespawn property. The handler processed the operation assuming the entity was fully active and valid.
If an attack transaction arrives precisely within the sub-millisecond window between the disconnect initialization and the tick cleanup phase, the server processes a lethal damage event against the disconnecting entity. The death event handler subsequently generates dropped item entities from the player's inventory, despite the inventory having already been saved to disk, resulting in duplication.
The patch applied in commit c0719b76b18f2508143134e79bc9f1aa39109683 introduces state validation checks within the discrete packet handlers. The maintainers opted for a functional workaround rather than redesigning the underlying World entity lookup logic. This approach mitigates the immediate attack vectors while preserving backward compatibility for existing plugins relying on the 5.x branch architecture.
The critical vulnerability existed in src/network/mcpe/handler/InGamePacketHandler.php. The vulnerable implementation fetched the target entity via getActorRuntimeId() and immediately executed interaction logic. The patched code introduces a strict conditional validation before processing the transaction data.
private function handleUseItemOnEntityTransaction(UseItemOnEntityTransactionData $data) : bool{
$target = $this->player->getWorld()->getEntity($data->getActorRuntimeId());
// Fix: Terminate transaction if the target is null or actively despawning
if($target === null || $target->isFlaggedForDespawn()){
return false;
}
// ... continuing interaction logic
}Secondary exploitation vectors required identical state validation implementations. In src/entity/object/ExperienceOrb.php, the logic was updated to verify !$entity->isFlaggedForDespawn() before selecting a target player for orbital pathing. Similarly, src/block/BaseSign.php received a $player->isConnected() check to prevent interaction events from firing against unlinked client sessions.
Exploitation of this vulnerability requires precise timing and coordination between two active network clients. No specialized exploitation tools or modified clients are necessary; standard game mechanics generate the required sequence of protocol packets. The attacker's objective is to induce a player state change simultaneously with an incoming attack transaction.
The methodology dictates the use of two accounts, acting as Player A and Player B. Player A serves as the inventory source and intentionally reduces their character's health to a minimum threshold. This ensures that a single incoming attack from Player B guarantees an instant server-side death event. Both characters are positioned in immediate proximity within the game environment.
Player A initiates a standard disconnection sequence, instructing the server to finalize the session and persist the inventory data. In the exact millisecond following the transmission of the disconnect signal, Player B executes a physical attack against Player A. The network latency must align such that Player B's attack packet arrives at the server processor after Player A's disconnect signal executes, but before the main server thread completes its tick and purges the entity lookup table.
If the timing conditions are successfully met, the server processes the death event on the transient entity. The software instantiates new item entities on the ground corresponding to the contents of Player A's inventory. Player B collects these physical entities, while Player A retains the original cryptographic copies of the items upon subsequent authentication.
The direct impact of GHSA-F9JP-856V-8642 is a compromise of application-specific data integrity. Attackers bypass systemic resource acquisition constraints to arbitrarily duplicate assets. This vulnerability breaks the intended mechanics of the server environment and degrades the economic balance of the platform.
The CVSS v3.1 score of 3.7 reflects the narrow technical scope and specific prerequisites of the flaw. The Attack Vector is Network (AV:N), but the Attack Complexity is High (AC:H) due to the strict millisecond timing window required for successful execution. Privileges Required evaluates to None (PR:N) and User Interaction is None (UI:N).
The impact Scope remains Unchanged (S:U), as the vulnerability is contained strictly within the server software context and does not permit lateral movement to the host operating system. Confidentiality and Availability impacts are None (C:N, A:N). Integrity evaluates to Low (I:L), representing the illicit modification of the application state without yielding administrative control or arbitrary code execution.
The definitive remediation for this vulnerability requires updating the PocketMine-MP server software deployment. System administrators must upgrade instances to version 5.39.2 or a subsequent stable release. The update explicitly integrates state validation parameters into the core packet transaction handlers, neutralizing the race condition without requiring widespread structural modifications.
The implementation within the 5.39.2 patch preserves full compatibility with the existing 5.x plugin ecosystem. The core Application Programming Interface (API) remains unaltered, ensuring a seamless upgrade path for production environments that rely on complex third-party extensions.
For environments operating under strict change control protocols where immediate patching is prohibited, administrators can apply a temporary mitigation utilizing the server's plugin architecture. Deploying a custom event listener effectively intercepts the exploitation sequence before the duplication logic is permitted to execute.
public function onDamage(EntityDamageByEntityEvent $event) : void {
$victim = $event->getEntity();
// Intercept transactions against despawning entities
if($victim instanceof Player && $victim->isFlaggedForDespawn()){
$event->cancel();
}
}CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
pocketmine/pocketmine-mp pmmp | < 5.39.2 | 5.39.2 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | Race Condition (TOCTOU) |
| CWE ID | CWE-362 |
| Attack Vector | Network |
| CVSS Score | 3.7 (Low) |
| Exploit Status | Weaponized / In the Wild |
| Impact | Integrity Compromise (Item Duplication) |
The software contains a race condition where an entity's lifecycle state and its presence in an active tracking resource are temporally misaligned, allowing concurrent network operations to process the entity multiple times.