TGViewer
Находки в опенсорсе: Python Находки в опенсорсе: Python @opensource_findings_python · 1.06K subscribers
Post #298 349
🚀 New issue to faststream-community/zMQTT by @borisalekseev
📝 MQTT 5 publish() silently succeeds when PUBACK or PUBREC rejects the message (#65)


Summary

MQTTClient.publish() returns normally when an MQTT 5 broker rejects a QoS 1 or QoS 2 PUBLISH with a negative acknowledgement reason code.

For example, Mosquitto returns 0x87 (Not authorized) for an ACL-denied publication:

Received PubAck(packet_id=1, reason_code=135, properties=None)

The message was not accepted by the broker, but await client.publish(...) completes without an exception.

Current behavior

For QoS 1, _handle_puback() resolves the publish future successfully without checking PubAck.reason_code.

For QoS 2, _handle_pubrec() also ignores the reason code and sends PUBREL even when PUBREC contains 0x87. MQTT 5 only permits PUBREL after a PUBREC reason code below 0x80.

The public MQTTClient.publish() method discards the acknowledgement returned by MQTTProtocol.publish().

Expected behavior
• PUBACK/PUBREC reason codes below 0x80, including 0x00 and 0x10 (No matching subscribers), complete successfully.
• A PUBACK or PUBREC reason code of 0x80 or greater raises a public MQTTPublishError.
• The exception exposes at least reason_code; exposing the optional Reason String would also be useful.
• A negative PUBREC completes and removes the QoS 2 flight, releases its packet identifier, and does not send PUBREL.
• The MQTT connection remains usable after the rejected operation.
• MQTT 3.1.1 behavior remains unchanged because PUBACK and PUBREC do not carry reason codes in that protocol version.

MQTTPublishError would be consistent with the existing MQTTSubscribeError.

Protocol references
MQTT 5.0 section 2.4: reason codes 0x80 and greater indicate failure.
MQTT 5.0 section 3.4.2.1: PUBACK 0x87 means the PUBLISH is not authorized.
MQTT 5.0 section 3.5.2.1: PUBREC has the same publish-rejection reason codes.
MQTT 5.0 section 4.3.3: PUBREL is sent only after a PUBREC reason code below 0x80.
MQTT 5.0 section 4.4: a negative PUBACK/PUBREC acknowledges the packet for retry purposes, but does not make the publication successful.
MQTT 3.1.1 section 3.3.5: when a PUBLISH is not authorized, the server must either send a positive acknowledgement or close the connection because the protocol has no negative publish acknowledgement.

Reproduction result

Reproduced with Mosquitto 2.1.2 and a read-only ACL:

MQTT 5 QoS 1:
Received PubAck(packet_id=1, reason_code=135, properties=None)
publish() returned normally

MQTT 5 QoS 2:
Received PubRec(packet_id=1, reason_code=135, properties=None)
QoS 2 PUBREC received, sent PUBREL
publish() returned normally

Mosquitto logs Denied PUBLISH for both messages.

Suggested tests
• QoS 1 negative PUBACK raises and releases the packet identifier.
• QoS 1 0x10 completes successfully.
• QoS 2 negative PUBREC raises, releases the packet identifier, and sends no PUBREL.
• Optional Reason String is preserved in the exception.
• MQTT 3.1.1 ACK behavior is unchanged.

#good_first_issue #faststream #zmqtt
sent via relator
  • 👍 1
More from @opensource_findings_python
  1. Sep 23, 2026🚀 New issue to ag2ai/faststream by @IvanKirpichnikov 📝 Feature: Implementation of the `A…
  2. Sep 22, 2026🚀 New issue to faststream-community/zMQTT by @borisalekseev 📝 Mark flaky Artemis test xf…
  3. Sep 17, 2026Помните про https://github.com/ozeranskii/httptap? Я писал о нем давно еще - > тут. Наклеп…
  4. Sep 15, 2026🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 `test_custom_union_form…
  5. Sep 13, 2026🚀 New issue to wemake-services/django-modern-rest by @milssky 📝 Changes in benchmarking…
  6. Sep 13, 2026🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Fix `operation_id` defa…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →