Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-39972

CVE-2026-39972: Mercure Protocol Auth Bypass Vulnerability

CVE-2026-39972 is an authentication bypass flaw in Mercure protocol caused by cache key collision that allows attackers to poison match results and bypass authorization. This article covers technical details, affected versions, impact, and mitigation steps.

Published:

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:

  1. The attacker identifies a target private topic pattern they wish to intercept or disrupt
  2. The attacker crafts a topic selector/topic pair that produces a hash collision with the target
  3. The attacker subscribes or publishes with the crafted values, poisoning the cache
  4. Subsequent authorization checks for the target topic incorrectly use the cached (poisoned) result
  5. 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:

go
 }
 
 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
bash
# 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.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.