Use pattern based access control lists that insert the client's username or client ID into the topic path. One line such as a write rule on sensor/%u/data then lets each device publish to its own branch and nowhere else. Combine it with required logins and a default of no access.
The problem with shared access
A broker with many devices and one set of rules tends to end up with all devices able to read and write all topics. If one device is stolen or compromised, the attacker can read every other device's data and publish false commands to them. Per device topic rules limit that damage to one device.
How pattern ACLs work in Mosquitto
The Mosquitto configuration manual describes an access control file. If an ACL file is defined, the topics it lists are the ones accessible. Each line grants an access type of read, write, readwrite or deny for a topic, and topics can use the usual + and # wildcards. Rules after a user line apply to that username. Note that the username is the one used in the password file, not the client ID.
Pattern lines use the same format but substitute values. %u matches the client's username and %c matches its client ID. The substitution must be the sole text for that level of the topic hierarchy, and pattern rules apply to all users. The manual's example is:
pattern write sensor/%u/data
With that rule, a device logged in as thermostat7 can write to sensor/thermostat7/data and to no other device's branch. The manual also notes that it is generally not possible to grant write access to the $SYS topic tree, with a stated exception for bridge connection state.
The manual suggests using the dedicated ACL file plugin instead of the older option, because plugins give more control over which listeners they apply to. It also points to the dynamic security plugin for administering clients and roles remotely.
Username or client ID
| Substitute | Pros | Cons |
|---|---|---|
| Username | Tied to a credential checked at login | Needs one credential per device |
| Client ID | Easy to set on devices | Chosen by the client unless otherwise enforced |
The safer pattern is to bind topics to the username, since the broker has verified it. A client ID is a label the client picks, so an attacker with any valid login might choose someone else's ID. Use client ID patterns when another control, such as certificates with an identity check, ties it to the credential.
The wildcard trap
The manual describes a plugin option that denies ACL checks when the username or client ID contains a plus or hash character. Its purpose is to prevent a malicious user from using wildcard characters in a name to match topics they should not. If you use a plugin that substitutes names into topics, check whether it has an equivalent option and enable it, and reject names containing wildcards at registration time.
Steps
- Require authentication on every listener first.
- Give each device its own username and credential. Avoid shared accounts.
- Design a topic tree with the device identity as one level, for example
devices/ID/telemetryanddevices/ID/commands. - Add pattern rules: write to the device's own telemetry branch, read from its own command branch.
- Add explicit rules for any shared topics, with read access where possible.
- Use deny rules for sensitive branches.
- Test with two device accounts. Device A must fail to subscribe to or publish on device B's topics, including through wildcard subscriptions.
- Reload rules and re test, since the manual notes existing subscriptions are affected after a reload.
What to log
Log failed publishes and subscribes. A device that repeatedly tries topics outside its branch is either misconfigured or compromised, and both are worth knowing about.
Try it yourself
Click through it at your own pace, or open it full screen.
Look at how API scan findings describe access problems, then think about what a two device test would show.
Quick check
Which is safer to match in an ACL, username or client ID?
Username, because the broker verified it at login. A client ID is chosen by the client unless another control enforces it.
Can a device use wildcards to read other devices' topics?
Yes, if the rules allow it. Test with a wildcard subscription from a second account, and deny names containing wildcard characters.
Safeguard scans your dependencies and SBOMs for known vulnerabilities, including MQTT libraries in your devices and services. A free scan is at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.