36 lines
3 KiB
Markdown
36 lines
3 KiB
Markdown
# UNDF: UNDF-2026-000000237
|
||
# RabbitMQ CWE-407 Scan — CLEAN (deeper scan, beyond rmq-0004)
|
||
|
||
**Date:** 2026-03-27
|
||
**Repo:** https://github.com/rabbitmq/rabbitmq-server
|
||
**Scan scope:** `deps/rabbit/src/rabbit_queue_index.erl` (renamed; checked `rabbit_classic_queue_index_v2.erl`), `rabbit_exchange.erl`, `rabbit_channel.erl`, `rabbit_stream_queue.erl`, `rabbit_quorum_queue.erl`, `rabbit_classic_queue.erl`, `rabbit_amqqueue.erl`
|
||
|
||
## Note on rabbit_queue_index.erl
|
||
|
||
The file `rabbit_queue_index.erl` no longer exists at the scan URL — it was replaced by
|
||
`rabbit_classic_queue_index_v2.erl` in current main.
|
||
|
||
## Findings
|
||
|
||
No new confirmed CWE-407 defects found beyond existing rmq-0001 through rmq-0004.
|
||
|
||
### Candidates examined
|
||
|
||
| File | Location | Pattern | Verdict |
|
||
|------|----------|---------|---------|
|
||
| `rabbit_exchange.erl` | `serialise_events/1` | `lists:any(fun (M) -> M:serialise_events(X) end, ...)` — iterates over a small, bounded list of exchange type modules | CLEAN (bounded) |
|
||
| `rabbit_channel.erl` | `check_resource_access/4` | `lists:member(V, Cache)` in per-operation permission check — Cache is bounded by `?MAX_PERMISSION_CACHE_SIZE = 12`; O(12) = O(1) | CLEAN (bounded) |
|
||
| `rabbit_channel.erl` | `check_topic_authorisation/5` | `lists:member({Resource, Context, Permission}, Cache)` — same bounded 12-entry cache | CLEAN (bounded) |
|
||
| `rabbit_classic_queue_index_v2.erl` | `ack_delete_fold_fun/3` | `lists:member(SeqId div SegmentEntryCount, Deletes)` inside `maps:fold` over `WriteBuffer` — O(W×D) where W=write buffer entries, D=deleted segments; `Deletes` is almost always empty or 1 entry; only triggered when a segment is fully acked; LOW severity, not a hot per-message path | CLEAN (rare path, bounded in practice) |
|
||
| `rabbit_classic_queue.erl` | `handle_event(down, ...)` | `lists:member(Pid, Status#msg_status.pending)` in `maps:fold` over unconfirmed — but `pending` is always `[QPid]` (1-element list per `qpids/3`); O(M×1) = O(M) | CLEAN (1-element list) |
|
||
| `rabbit_stream_queue.erl` | `grow/4` | `lists:member(Node, Nodes)` in list comprehension per queue — `Nodes` is queue replica set (typically 1–5); called in management operations | CLEAN (bounded) |
|
||
| `rabbit_quorum_queue.erl` | `cleanup_data_dir/0` | `lists:member(Name, Running)` for each Registered ra server — O(R×Q); maintenance/startup path, not per-message | CLEAN (admin path) |
|
||
| `rabbit_amqqueue.erl` | `check_declare_arguments/3` | `lists:filter(fun({Arg,_}) -> lists:member(Arg, QueueTypeArgs) end, ...)` — O(A×T); called once per queue declare, not per message | CLEAN (declare-time) |
|
||
|
||
## Summary
|
||
|
||
The permission cache in `rabbit_channel.erl` has a constant-bounded `lists:member`
|
||
(max 12 elements). The `ack_delete_fold_fun` in `rabbit_classic_queue_index_v2.erl`
|
||
has a theoretical O(W×D) complexity but `D` (deleted segments) is almost always 0 or 1
|
||
in normal operation and the code path is only entered on full-segment ack completion.
|
||
No hot per-message O(N²) patterns found beyond the four already patched defects.
|