Описание
Incomplete fix for CVE-2026-44838: escape_regex_char/1 does not escape -, leaving room for an MQTT topic permission bypass
Affected product
RabbitMQ — internal authorization backend + rabbitmq_mqtt plugin topic permissions
Summary
The CVE-2026-44838 fix made expand_topic_permission/2 escape regex metacharacters in expanded topic-permission variables (escape_regex(V)), but escape_regex_char/1 escapes \ ^ $ . | ? * + ( ) [ ] { } and omits -. When a topic permission template places {client_id} inside a [...] character class (e.g. ^[{client_id}]-sensors$), an MQTT client using client_id = a-z expands the regex to ^[a-z]-sensors$, turning the class into a range and broadening topic authorization to b-sensors, m-sensors, etc. The repository's own OAuth2 scope-expansion code explicitly escapes - for exactly this reason.
Affected code
deps/rabbit/src/rabbit_auth_backend_internal.erl→escape_regex_char/1(no$-).deps/rabbitmq_mqtt/src/rabbit_mqtt_processor.erl→ injects user-controlledclient_idinto the topic variable map; read and write checks share the same backend expansion.
Steps to reproduce
Using the provided reproduction materials, With set_topic_permissions ... '^[{client_id}]-sensors$':
mosquitto_pub -i 'a-z' -t 'b-sensors'→ PUBACK (bypass);mosquitto_pub -i 'x' -t 'b-sensors'→ denied (control).
(Runtime-confirmed on official rabbitmq:4.3.2-management; a single benign placeholder message was published.)
Impact
A low-privileged authenticated MQTT user controlling its client_id can broaden topic authorization (read and write) when templates embed {client_id} in a [...] class. Narrower than the original raw-regex injection (requires that template shape), but RabbitMQ supports regex topic permissions and its OAuth2 tests already treat this range class as security-relevant.
Suggested remediation
Add $- to escape_regex_char/1, matching the OAuth2 implementation. Add a regression test (analogous to OAuth2 crafted_value_cannot_form_range_inside_char_class): expand_topic_permission(<<"^[{client_id}]-sensors$">>, #{<<"client_id">> => <<"a-z">>}) should yield <<"^[a\\-z]-sensors$">>, and b-sensors must be denied.
Credit
Reported as part of an incomplete-patch measurement study (responsible disclosure).
Пакеты
rabbitmq
>= 4.3.2, < 4.3.3
4.3.3
rabbitmq
>= 4.2.0, < 4.2.9
4.2.9
rabbitmq
>= 4.1.0, < 4.1.14
4.1.14
rabbitmq
>= 4.0.0, < 4.0.23
4.0.23
5.1 Medium
CVSS4
CVE ID
5.1 Medium
CVSS4