Skip to content

in_mqtt: reject truncated publish packets#11580

Merged
edsiper merged 1 commit into
masterfrom
mqtt-fixt
Mar 18, 2026
Merged

in_mqtt: reject truncated publish packets#11580
edsiper merged 1 commit into
masterfrom
mqtt-fixt

Conversation

@edsiper
Copy link
Copy Markdown
Member

@edsiper edsiper commented Mar 18, 2026


Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

Bug Fixes

  • Enhanced MQTT message validation by adding checks for truncated or incomplete data during message processing, ensuring proper error detection and handling of malformed messages.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 18, 2026

📝 Walkthrough

Walkthrough

Added buffer boundary validations in the MQTT publish message handler to prevent unsafe memory reads. The function now checks available bytes before reading topic length, packet identifier (when QoS > 0), and payload data, returning early on insufficient data with appropriate error logging.

Changes

Cohort / File(s) Summary
MQTT Publish Handler Validation
plugins/in_mqtt/mqtt_prot.c
Added pre-read boundary checks in mqtt_handle_publish: validates ≥2 bytes before reading topic length, validates packet identifier availability for QoS > 0, and verifies buffer position within frame bounds before payload processing. Returns -1 and logs errors on truncated data.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 Hop, skip, and a bounds-check spree!
No more reading past what we see,
Two bytes we peek before we leap,
MQTT payloads safe and deep! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'in_mqtt: reject truncated publish packets' accurately and specifically describes the main change: adding validation to reject MQTT PUBLISH packets with truncated or insufficient data.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mqtt-fixt
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce8dc0a885

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/in_mqtt/mqtt_prot.c Outdated
Comment on lines +329 to +331
if (conn->buf_pos > conn->buf_frame_end) {
flb_plg_debug(ctx->ins, "truncated publish payload");
return -1;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Don't reject valid zero-byte PUBLISH payloads

buf_pos can legitimately advance to buf_frame_end + 1 when a PUBLISH frame contains only the topic (and optional packet id) with an empty payload, so this condition turns a valid no-payload publish into -1. In the current flow that propagates through mqtt_prot_parser() and mqtt_conn_event() into a connection teardown (plugins/in_mqtt/mqtt_prot.c:453-456, plugins/in_mqtt/mqtt_conn.c:63-66). Before this change the same case simply reached mqtt_data_append() with msg_len == 0 and was dropped/logged, so clients that use empty publishes (for example retained-message clears/tombstones) now regress from a no-op to a disconnect.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/in_mqtt/mqtt_prot.c`:
- Around line 329-332: The truncation check in mqtt_prot.c incorrectly rejects a
valid zero-length PUBLISH payload because it treats conn->buf_pos ==
conn->buf_frame_end + 1 as truncated; update the condition to allow that
boundary by only treating positions beyond that as truncation (change the check
that currently uses conn->buf_pos and conn->buf_frame_end so it tests
conn->buf_pos > conn->buf_frame_end + 1), keeping the existing
flb_plg_debug("truncated publish payload") path for true truncation cases.
- Around line 278-281: The checks in mqtt_prot.c that use BUF_AVAIL() and
conn->buf_len (e.g., the branch that logs "truncated publish topic length" and
the hlen comparison) must be changed to use frame-local bounds so a truncated
PUBLISH cannot borrow bytes from the next coalesced frame; calculate available
bytes as (conn->buf_frame_end - conn->buf_pos) or otherwise use
conn->buf_frame_end when validating lengths, replace uses of BUF_AVAIL() and
conn->buf_len in the relevant validation blocks (the truncated-topic-length
check and the hlen vs buf_len check) with that frame-local available value, and
return -1 on failure as before.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7835c61a-039e-4a84-99f7-c1814a7e0f2f

📥 Commits

Reviewing files that changed from the base of the PR and between 8f771e7 and ce8dc0a.

📒 Files selected for processing (1)
  • plugins/in_mqtt/mqtt_prot.c

Comment thread plugins/in_mqtt/mqtt_prot.c Outdated
Comment on lines +278 to +281
if (BUF_AVAIL() < 2) {
flb_plg_debug(ctx->ins, "truncated publish topic length");
return -1;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use frame-local bounds here, not BUF_AVAIL() / conn->buf_len.

Line 278 and Line 301 validate against the full receive buffer, and Line 288 compares hlen against conn->buf_len. With coalesced packets, a truncated current PUBLISH can still consume bytes from the next frame before failing. These checks should be bounded by conn->buf_frame_end.

Proposed patch
-    if (BUF_AVAIL() < 2) {
+    if (conn->buf_pos + 1 > conn->buf_frame_end) {
         flb_plg_debug(ctx->ins, "truncated publish topic length");
         return -1;
     }
@@
-    if (hlen > (conn->buf_len - conn->buf_pos)) {
+    if (hlen > (conn->buf_frame_end - conn->buf_pos)) {
         flb_plg_debug(ctx->ins, "invalid topic length");
         return -1;
     }
@@
-        if (BUF_AVAIL() < 2) {
+        if (conn->buf_pos + 1 > conn->buf_frame_end) {
             flb_plg_debug(ctx->ins, "truncated publish packet id");
             return -1;
         }

Also applies to: 288-291, 301-304

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_mqtt/mqtt_prot.c` around lines 278 - 281, The checks in
mqtt_prot.c that use BUF_AVAIL() and conn->buf_len (e.g., the branch that logs
"truncated publish topic length" and the hlen comparison) must be changed to use
frame-local bounds so a truncated PUBLISH cannot borrow bytes from the next
coalesced frame; calculate available bytes as (conn->buf_frame_end -
conn->buf_pos) or otherwise use conn->buf_frame_end when validating lengths,
replace uses of BUF_AVAIL() and conn->buf_len in the relevant validation blocks
(the truncated-topic-length check and the hlen vs buf_len check) with that
frame-local available value, and return -1 on failure as before.

Comment thread plugins/in_mqtt/mqtt_prot.c Outdated
Comment on lines +329 to +332
if (conn->buf_pos > conn->buf_frame_end) {
flb_plg_debug(ctx->ins, "truncated publish payload");
return -1;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Current payload truncation check rejects valid empty PUBLISH payloads.

Line 329 treats conn->buf_pos == conn->buf_frame_end + 1 as truncation, but that is a valid zero-byte payload boundary in MQTT. This can disconnect clients for legal packets.

Proposed patch
-    if (conn->buf_pos > conn->buf_frame_end) {
+    if (conn->buf_pos > conn->buf_frame_end + 1) {
         flb_plg_debug(ctx->ins, "truncated publish payload");
         return -1;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (conn->buf_pos > conn->buf_frame_end) {
flb_plg_debug(ctx->ins, "truncated publish payload");
return -1;
}
if (conn->buf_pos > conn->buf_frame_end + 1) {
flb_plg_debug(ctx->ins, "truncated publish payload");
return -1;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_mqtt/mqtt_prot.c` around lines 329 - 332, The truncation check in
mqtt_prot.c incorrectly rejects a valid zero-length PUBLISH payload because it
treats conn->buf_pos == conn->buf_frame_end + 1 as truncated; update the
condition to allow that boundary by only treating positions beyond that as
truncation (change the check that currently uses conn->buf_pos and
conn->buf_frame_end so it tests conn->buf_pos > conn->buf_frame_end + 1),
keeping the existing flb_plg_debug("truncated publish payload") path for true
truncation cases.

Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant