Aug 28, 2026·7 min read·0 visits
A key-erasure flaw in cakephp/queue's deduplication mechanism allows distinct job parameters to resolve to identical unique hashes, enabling attackers to silently drop legitimate background jobs.
An incomplete array comparison vulnerability in cakephp/queue version 0.1.11 through 2.3.0 allows unauthenticated attackers to cause key collisions in unique job deduplication. This is caused by standard array value sorting that discards associative keys, normalizing different payload keys to identical arrays and leading to a denial of service (DoS) by dropping legitimate jobs.
The cakephp/queue library is an integration-compatible queueing framework designed for the CakePHP ecosystem. Background execution is managed via jobs that are pushed to backends such as Redis, MySQL, or RabbitMQ. To handle asynchronous flows securely, the library provides duplicate mitigation features to restrict multiple identical jobs from executing concurrently. Developers enable this by defining $shouldBeUnique = true in their Job class definitions.\n\nWhen duplicate protection is active, the queue library must produce a consistent, unique fingerprint for each task based on its context. The identification logic resides within the QueueManager::getUniqueId() method, which calculates an MD5 hash of the concatenated class name, method, and serialized parameters. The design objective of this deduplication process is to guarantee that identical payloads are detected and handled without race conditions.\n\nHowever, the mechanism used to normalize incoming associative array arguments exposes a critical vulnerability. Due to a coding error in how parameters are canonicalized, the deduplication engine can be forced to treat distinct data payloads as identical. This leads to a logical collision where semantically unrelated jobs resolve to the same unique identifier, presenting a medium-to-low severity denial of service attack surface.
The core of the vulnerability lies in the implementation of the parameter canonicalization logic within QueueManager::getUniqueId(). In vulnerable versions, the library utilizes PHP's standard sort() function on the parameter array $data before serialization. The original engineering intent of this step was to ignore parameter ordering variations, ensuring that ['id' => 1, 'type' => 'active'] and ['type' => 'active', 'id' => 1] resolve to the same hash.\n\nWhile sorting satisfies canonicalization, PHP's native sort() function modifies the input array by value and discards all original keys. The function assigns new sequential, integer-based numeric keys (0, 1, 2, ...) to the sorted array elements. Consequently, any distinction derived from the keys of an associative array is entirely lost during this step, which neutralizes the uniqueness of parameter keys.\n\nThis behavior causes any two associative arrays containing the exact same values, regardless of their keys, to normalize into identical numerical arrays. For instance, the array ['user' => 'admin', 'action' => 'delete'] and ['field' => 'admin', 'context' => 'delete'] both contain the values 'admin' and 'delete'. After processing with sort(), both structures are converted to [0 => 'admin', 1 => 'delete']. The following serialize() call outputs the exact same string representation for both, generating a duplicate key collision.
The vulnerability was resolved in version 2.3.1 by modifying QueueManager::getUniqueId() to replace the native sort() function with a custom recursive key sorting function.\n\nphp\n// Vulnerable implementation in cakephp/queue < 2.3.1\npublic static function getUniqueId(string $class, string $method, array $data): string\n{\n // Bug: sort() discards associative keys and reindexes numerically\n sort($data);\n\n $hashInput = implode('', [\n $class,\n $method,\n serialize($data),\n ]);\n\n return hash('md5', $hashInput);\n}\n\n\nphp\n// Patched implementation in cakephp/queue 2.3.1\npublic static function getUniqueId(string $class, string $method, array $data): string\n{\n // Fix: Recursively sorts by keys to preserve associative array keys\n $data = static::sortUniqueValues($data);\n\n $hashInput = implode('', [\n $class,\n $method,\n serialize($data),\n ]);\n\n return hash('md5', $hashInput);\n}\n\nprotected static function sortUniqueValues(array $data): array\n{\n foreach ($data as $key => $value) {\n if (is_array($value)) {\n $data[$key] = static::sortUniqueValues($value);\n }\n }\n ksort($data);\n\n return $data;\n}\n\n\nReviewing the patched solution, the implementation of sortUniqueValues introduces recursive traversal of nested arrays. It replaces the value-based sort() with ksort(), which sorts elements strictly by key name while fully retaining key-value mappings. This guarantees that parameters with different keys produce distinct serialization signatures.\n\nHowever, a structural design risk persists. The $hashInput value is generated by concatenating $class, $method, and the serialized $data directly without a separating delimiter. This approach makes the hashing algorithm susceptible to a boundary-shifting namespace collision. An attacker who can influence class or method registration can craft matching inputs (e.g., class App\\Job\\AdminTask and method run vs. class App\\Job\\Admin and method Taskrun) to force identical hash strings. Using a null byte or unique separator between values would mitigate this remaining vector.
To exploit the key-collision flaw, an attacker must identify a queue-backed feature that accepts user-defined associative payloads and uses deduplication. The attacker aims to block a high-privilege background job from executing by priming the deduplication cache with a lower-privilege job containing matching values but different keys.\n\nFor example, consider a scenario where administrative jobs execute a deletion using the parameters ['target_user' => 'admin', 'action' => 'delete']. An attacker with lower-level access can locate an unauthenticated or low-privilege feature that queue-processes tasks using the same class and method, such as user logging. The attacker submits a payload of ['arbitrary_key' => 'admin', 'log_level' => 'delete'].\n\nWhen the attacker's payload is pushed, the queue manager processes the array, discards the keys 'arbitrary_key' and 'log_level' via sort(), and generates the hash based on values 'admin' and 'delete'. When the administrative action is subsequently triggered, its parameters are similarly normalized, generating the exact same unique ID. The queue manager, seeing the existing active unique ID in the cache, assumes a duplicate execution is occurring and silently drops the legitimate administrative job.\n\nmermaid\ngraph LR\n A["Attacker submits low-privilege job with values 'admin'/'delete'"] --> B["QueueManager processes getUniqueId()"]\n B --> C["sort() discards keys, normalizing array to values only"]\n C --> D["Cache stores MD5 hash for normalized array"]\n E["Admin triggers high-privilege job with values 'admin'/'delete'"] --> F["QueueManager calculates hash for high-privilege job"]\n F --> G["Keys discarded, resulting in identical normalized array"]\n G --> H["MD5 hash matches the active cache entry"]\n H --> I["Legitimate job silently dropped (DoS)"]\n D -.-> H\n
The CVSS score for this vulnerability is rated at 3.7 (Low Severity) with the vector CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L. The low rating is primarily because the vulnerability cannot be used to read unauthorized data, escalate privileges directly, or execute arbitrary code. The operational impact is limited to availability, as it allows attackers to prevent specific background tasks from running.\n\nDespite the low severity score, the real-world operational risk can be significant depending on the role of the queue system. In production environments, background jobs are often utilized for critical functions such as payment processing, email notifications, multi-factor authentication dispatch, and data synchronization. If an attacker can systematically drop these background processes, it can cause database desynchronization and functional disruption.\n\nThe attack complexity is classified as high (AC:H) because the attacker needs prior knowledge of the target class, target method, and parameter values. Additionally, the exploit is time-sensitive, as the collision must occur while the colliding unique ID is still active in the deduplication cache. Once the original job is processed and its cache entry expires, the block is cleared.
The primary and recommended solution is to upgrade the cakephp/queue dependency to version 2.3.1 or later. This release completely eliminates the use of sort() inside unique key generation, replacing it with recursive ksort(). This ensures parameter structures are sorted by keys and associative structures remain fully distinct during serialization.\n\nIf immediate upgrading is blocked by legacy dependencies, teams can implement workarounds at the application level. One approach is to programmatically override the standard queue manager class or bypass $shouldBeUnique = true for tasks that receive user-controlled input arrays. Alternatively, developers can sanitize and validate incoming payload schemas to ensure user-defined structures cannot mimic high-privilege patterns.\n\nFor deep visibility, security teams should implement monitoring alerts for duplicate job detections within the queue logs. An unusual increase in duplicate rejections, particularly for critical administrative actions, can serve as a high-fidelity indicator of a targeted key collision attack.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
cakephp/queue CakePHP | >= 0.1.11, < 2.3.1 | 2.3.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-1023 |
| Attack Vector | Network (AC: High) |
| CVSS Score | 3.7 |
| EPSS Score | 0.00 |
| Impact | Availability (Low) |
| Exploit Status | Proof-of-Concept / None |
| KEV Status | Not Listed |
The application performs a comparison that omits critical factors or attributes, leading to incorrect validation or collision.
An input buffering vulnerability exists in the aiosmtplib asynchronous SMTP client library before version 5.1.2. When upgrading a plaintext connection to TLS via STARTTLS, the library processes buffered plaintext responses after transport negotiation has completed. This behavior allows a network-positioned attacker to inject spoofed server responses prior to negotiation, leading to command/response desynchronization, arbitrary capability injection, and potential credential theft.
An open redirect vulnerability exists in WebOb before version 1.8.11 due to a parser differential between WebOb's validation logic and Python's standard urllib.parse.urljoin() function. Under Python 3.10+, the urljoin function strips leading and trailing space characters and C0 control characters, which allowed specially crafted inputs to bypass WebOb's prefix checks while still resolving as off-host redirects.
Prior to version 1.0.0, the n8n-nodes-sqlite3 integration exposed the db_path parameter as an unrestricted node parameter. By default, n8n node parameters allow the evaluation of dynamic data expressions, meaning untrusted external input could be mapped to the database path. This vulnerability allows an external attacker to control which SQLite database file the n8n backend process attempts to open, leading to directory traversal outside of the intended directory context.
A client-side open redirect vulnerability has been identified in the Kargo user interface. The flaw resides in the handling of OpenID Connect (OIDC) login and token renewal flows, where the application extracts an unvalidated destination path from the redirectTo query parameter. Attackers can exploit this to redirect authenticated users to arbitrary external domains.
A Server-Side Template Injection (SSTI) vulnerability in the Silverstripe Advanced Workflow module allows authenticated attackers with workflow authoring permissions to achieve arbitrary code execution. By manipulating the NotifyUsersWorkflowAction.EmailTemplate field, attackers can inject template code that dynamically executes arbitrary PHP commands via the core translation helper interpolation path.
A path traversal and arbitrary file write vulnerability exists in the libreoffice-convert Node.js package in all versions prior to 1.8.2. The convertWithOptions function fails to validate or sanitize the caller-controlled options.fileName parameter, allowing directory traversal sequences to write files outside the temporary directory.