The vulnerability, CVE-2026-73846, describes a cache-key canonicalization collision in the CKAN MCP Server. The core issue lies in how cache keys are generated from request parameters, specifically within the canonicalizeParams and buildCacheKey functions in src/utils/cache.ts.
canonicalizeParams was vulnerable because it joined sorted ${key}=${value} pairs using '&' as a delimiter without escaping special characters like '&' or '=' within the values. This allowed an attacker to craft a parameter value containing '&' to effectively inject additional key-value pairs into the canonicalized string, leading to collisions. For example, { q: 'budget', rows: 10 } and { q: 'budget&rows=10' } would produce the same canonical string q=budget&rows=10. Furthermore, the serialization of objects versus strings (JSON.stringify(value) vs String(value)) could also lead to ambiguities.
buildCacheKey compounded this issue by concatenating serverUrl, action, and the output of canonicalizeParams using '|' as a delimiter, also without escaping. This meant that if an attacker could control parts of these inputs, they could further exploit the unescaped delimiters to force collisions.
The provided commit 8e1522f9bbfa1f3b21550f17887f60f133e24151 clearly shows the remediation. The canonicalizeParams function was refactored to use JSON.stringify(canonicalizeValue(filtered)) which ensures a typed, recursively sorted JSON serialization, eliminating the unescaped '&' delimiter and the object-vs-string ambiguity. The buildCacheKey function was also updated to use JSON.stringify([serverUrl, action, canonicalizeParams(params)]), which unambiguously frames the components as a JSON array, preventing collisions due to unescaped '|' characters. The canonicalizeValue function was introduced as part of the fix to handle recursive sorting and type preservation during JSON serialization, and thus is not a vulnerable function itself but a part of the mitigation.
Exploitation would involve an attacker sending a specially crafted request that, due to the flawed canonicalization, generates the same cache key as a legitimate request. The attacker's response would then be cached, and subsequent legitimate requests with different logical parameters but the same colliding cache key would receive the attacker's poisoned response. This leads to cache poisoning/confusion and integrity compromise.