CVE-2026-39972 Overview
CVE-2026-39972 is an authorization bypass vulnerability in Mercure, a protocol for pushing data updates to web browsers and other HTTP clients in a battery-efficient way. Prior to version 0.22.0, a cache key collision vulnerability in the TopicSelectorStore component allows an attacker to poison the match result cache. This can cause private updates to be delivered to unauthorized subscribers or block delivery to legitimate authorized subscribers.
Critical Impact
Attackers who can subscribe to the hub or publish updates with crafted topic names can exploit cache key collisions to bypass authorization checks on private updates, potentially exposing sensitive real-time data to unauthorized parties.
Affected Products
- Mercure Hub versions prior to 0.22.0
- Applications using Mercure's TopicSelectorStore with caching enabled
- Deployments using Caddy with Mercure module prior to the security patch
Discovery Timeline
- 2026-04-09 - CVE CVE-2026-39972 published to NVD
- 2026-04-09 - Last updated in NVD database
Technical Details for CVE-2026-39972
Vulnerability Analysis
The vulnerability exists in the TopicSelectorStore component of Mercure, which is responsible for matching topic selectors to topics when determining which subscribers should receive updates. To improve performance, Mercure implements a caching mechanism for match results. However, the cache key construction method was fundamentally flawed.
The cache key was constructed by concatenating the topic selector and topic with an underscore separator. Since both topic selectors and topics can legitimately contain underscores, two completely distinct pairs of selector/topic combinations can produce identical cache keys. This creates a collision scenario where an attacker can pre-populate the cache with a malicious entry that will be incorrectly returned for a different, legitimate selector/topic pair.
For example, a topic selector private_updates combined with topic secret would produce the key private_updates_secret. However, a selector private with topic updates_secret would produce the exact same key. An attacker controlling the latter pair can poison the cache to affect authorization decisions for the former.
Root Cause
The root cause is improper cache key construction (CWE-1289: Improper Validation of Unsafe Equivalence in Input). The underscore character used as a delimiter was not a reserved character, meaning it could appear in both topic selectors and topics themselves. This ambiguity in the key construction algorithm created an equivalence class of inputs that should have been distinct but were treated as identical by the caching layer.
Attack Vector
The attack vector is network-based and requires low privileges. An attacker who can subscribe to the Mercure hub or publish updates with controlled topic names can exploit this vulnerability. The attack flow involves:
- The attacker identifies a target private topic pattern they wish to intercept or disrupt
- The attacker crafts a topic selector/topic pair that produces a hash collision with the target
- The attacker subscribes or publishes with the crafted values, poisoning the cache
- Subsequent authorization checks for the target topic incorrectly use the cached (poisoned) result
- Private updates may be delivered to the attacker or blocked from legitimate subscribers
The fix modifies the caching infrastructure as shown in the security patch:
}
type TopicSelectorCacheConfig struct {
- MaxEntriesPerShard int `json:"max_entries_per_shard,omitempty"`
- ShardCount uint64 `json:"shard_count,omitempty"`
+ // Deprecated: use Size instead.
+ MaxEntriesPerShard int `json:"max_entries_per_shard,omitempty"`
+ // Deprecated: no longer used.
+ ShardCount uint64 `json:"shard_count,omitempty"`
+ // Size is the maximum number of entries in the cache.
+ Size int `json:"size,omitempty"`
Source: GitHub Commit Details
Detection Methods for CVE-2026-39972
Indicators of Compromise
- Unexpected subscription patterns with topics containing unusual underscore combinations
- Authorization failures or unexpected authorization successes in Mercure hub logs
- Subscribers receiving updates for topics they should not have access to
- Legitimate subscribers reporting missing updates for private topics
Detection Strategies
- Monitor Mercure hub logs for subscription requests with crafted topic patterns designed to create collisions
- Implement anomaly detection for topics that deviate from expected naming conventions
- Review access logs for patterns where users receive data from topics outside their normal authorization scope
- Enable detailed logging of cache hits and misses in TopicSelectorStore to identify potential collision attacks
Monitoring Recommendations
- Configure alerting on authorization decision reversals within short time windows
- Monitor for rapid subscription/unsubscription patterns that could indicate cache poisoning attempts
- Track topic naming patterns and alert on deviations from established conventions
- Implement real-time analysis of Mercure hub metrics to detect unusual cache behavior
How to Mitigate CVE-2026-39972
Immediate Actions Required
- Upgrade Mercure to version 0.22.0 or later immediately
- Review Mercure hub logs for any suspicious subscription or publication patterns
- Audit topic naming conventions to identify any potentially colliding topic/selector pairs
- Temporarily disable caching in TopicSelectorStore if upgrade cannot be performed immediately
Patch Information
The vulnerability is fixed in Mercure version 0.22.0. The patch addresses the cache key collision issue by modifying the caching infrastructure. Technical details of the fix are available in the GitHub Commit and the GitHub Security Advisory.
Workarounds
- Disable TopicSelectorStore caching entirely until the patch can be applied
- Implement strict topic naming conventions that prevent underscore usage in critical positions
- Add an application-layer authorization check before delivering updates to subscribers
- Use a reverse proxy to filter subscription requests with suspicious topic patterns
# Configuration example - Update Mercure cache configuration
# In your Caddyfile or mercure configuration, update the cache settings:
mercure {
# Use the new Size parameter instead of deprecated options
topic_selector_cache {
size 10000
}
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


