LwM2M is the OMA SpecWorks protocol for managing constrained IoT devices. A client on the device exposes numbered objects such as Device (3) and Firmware Update (5) over CoAP, a bootstrap server provisions its credentials, and a management server reads, writes and updates it. Secure it with unique per device keys, DTLS or OSCORE, and signed firmware.
This post extends our explainers on CoAP, DTLS and OSCORE, MQTT 5 and LoRaWAN. The CoAP post covers the message layer; here we stay one level up, using the LwM2M 1.2.2 Core and Transport specifications, the IETF RFCs they cite and the docs of the main open source implementations.
Key takeaways
- LwM2M is published by OMA SpecWorks. Version 1.0 shipped in February 2017, 1.1 in July 2018, 1.2 in November 2020, and the current revision, 1.2.2, in June 2024.
- Three roles (Client, Server, Bootstrap-Server) talk over four interfaces: Bootstrap, Client Registration, Device Management and Service Enablement, and Information Reporting.
- Everything is addressed as Object/Instance/Resource. Reading /3/0/0 returns the manufacturer. IDs 0 to 1023 belong to OMA, 2048 to 10240 to other standards bodies (IPSO Temperature is 3303), and 10241 to 32768 to vendors.
- The Security object (0) has five modes: 0 Pre-Shared Key, 1 Raw Public Key, 2 Certificate, 3 NoSec, 4 Certificate with EST. Management servers can never read or write it; only the bootstrap server can.
- The Transport specification requires mutual authentication, encryption, integrity protection and unique keys per client. NoSec is only allowed when another layer provides security.
- CoAP over DTLS on UDP port 5684 is the default. 1.1 added TCP and TLS and OSCORE; 1.2 added HTTP and MQTT, DTLS and TLS 1.3, and the DTLS Connection ID.
- The Firmware Update object has four states and twelve result codes. It moves and triggers an image; it does not define signing. That belongs to the device's update code and to manifest formats such as IETF SUIT.
- Eclipse Leshan (Java) is maintained. Eclipse Wakaama (C) was archived on 15 September 2026, and its README says its only official release, 1.0, has security issues and is unsupported.
What LwM2M is and what problem it solves
The Core specification describes LwM2M as the application protocol between a LwM2M Server or Bootstrap-Server and a LwM2M Client, covering "device management and service enablement for LwM2M Devices", with a messaging layer "inspired by the RESTful design model based on CoAP". OMA's overview adds that it uses CoAP, CBOR and SenML to keep power and data use low and offers "over 400 ready-to-use objects and resources".
The problem is old. A fleet of battery powered meters or trackers needs the same management functions as any computer: identify it, read values, change configuration, rotate credentials, push firmware and confirm the result. Before LwM2M, teams adapted protocols built for bigger devices or invented a topic layout on a message broker. LwM2M standardises the operations and the data model so a client from one vendor works with a server from another.
Version history
| Version | Date | Main changes, per OMA and the Core specification |
|---|---|---|
| 1.0 | February 2017 | Object model, four interfaces, CoAP over UDP and SMS, DTLS, objects 0 to 7 |
| 1.0.1 | July 2017 | Bug fixes |
| 1.0.2 | February 2018 | Fixes and clarifications |
| 1.1 | July 2018 | Incremental bootstrap, better PKI and EST, CoAP over TCP and TLS, OSCORE (object 21), LoRaWAN and 3GPP CIoT, SenML JSON and CBOR |
| 1.1.1 | June 2019 | Corrections |
| 1.2 | November 2020 | HTTP and MQTT transports, Bootstrap-Pack-Request, gateways, LwM2M CBOR, enhanced firmware update, TLS and DTLS 1.3, Connection ID, objects 23 to 27 |
| 1.2.1 | December 2022 | Security and transport updates |
| 1.2.2 | June 2024 | Bug fixes; current release |
The Core specification says 1.2 is backwards compatible with 1.0 and 1.1 for mandatory features, and that a server should support all clients of its major version. That matters because many deployed clients still speak 1.0.x: the Zephyr RTOS library, for example, implements 1.0.2 by default and 1.1.1 with a Kconfig option.
How it differs from TR-069 and ad hoc MQTT management
TR-069, the Broadband Forum's CPE WAN Management Protocol, was first issued in May 2004; the current text is Amendment 6 Corrigendum 1 (June 2020). An Auto-Configuration Server manages home gateways and set top boxes with SOAP over HTTP and TLS, using large XML data models such as TR-181 Device:2. That suits a mains powered router, not a coin cell sensor on a narrowband link.
MQTT with a home grown topic scheme is the other common route. MQTT standardises messaging, not management, so each team designs its own payloads, update flow and provisioning, and each design is a place to forget security. LwM2M 1.2 can itself run over MQTT 3.1.1 or 5; what it adds is the shared data model and operations.
Architecture: client, server and bootstrap server
- The LwM2M Client runs on the device and holds the objects.
- The LwM2M Server registers and manages clients: reads, writes, observes, executes and drives firmware updates. A client can have accounts on several servers.
- The LwM2M Bootstrap-Server writes credentials and server accounts into the client.
The Transport specification says the client is always the TLS or DTLS client and both servers always act as TLS or DTLS servers, so sleeping devices behind carrier NAT always open the session.
The four interfaces
| Interface | Operations | Purpose |
|---|---|---|
| Bootstrap | Bootstrap-Request, Bootstrap-Pack-Request (uplink); Bootstrap-Write, Bootstrap-Read, Bootstrap-Discover, Bootstrap-Delete, Bootstrap-Finish (downlink) | Writing server accounts and keys into the client |
| Client Registration | Register, Update, De-register | Announcing the device, its objects, lifetime and binding |
| Device Management and Service Enablement | Create, Read, Read-Composite, Write, Write-Composite, Delete, Execute, Write-Attributes, Discover | Reading and changing resources, executing actions such as reboot |
| Information Reporting | Observe, Observe-Composite, Cancel Observation, Notify, Send | Subscriptions and unsolicited data |
Two rules carry most of the security weight. The client must ignore management operations from a server until registration with it completes. And on the management and reporting interfaces the client must reject any operation on the Security (0), OSCORE (21) and COSE (23) objects. A compromised management server cannot read device keys through LwM2M.
Registration, lifetime and queue mode
On Register the client sends its endpoint name, lifetime, binding and object list. The Server object's Lifetime resource (/1/x/1) sets the lifetime in seconds; the client refreshes it with Update, and if it lapses the server must treat the client as de-registered. Servers can request an update by executing /1/x/8. In queue mode the server holds requests while a device sleeps. The Transport specification warns that combining it with cellular network buffering can cause duplicate delivery on wake.
How the object model works
Every item has a path of Object ID, Instance ID and Resource ID. The Core specification's plain text example:
Req: Read /3/0/0
Res: 2.05 Content
Open Mobile Alliance
Object 3 is Device, instance 0 its only instance, resource 0 Manufacturer. Device also defines 3 Firmware Version, 4 Reboot (executable), 13 Current Time and 20 Battery Status. Each resource definition states its operations (R, W, RW or E), multiplicity, type and range.
The core objects
| ID | Object | Since | Holds |
|---|---|---|---|
| 0 | LwM2M Security | 1.0 | Server URI, bootstrap flag, security mode, keys, Short Server ID |
| 1 | LwM2M Server | 1.0 | Lifetime, binding, update and bootstrap triggers |
| 2 | Access Control | 1.0 | Which server may do what to which instance |
| 3 | Device | 1.0 | Manufacturer, versions, reboot, time, battery |
| 4 | Connectivity Monitoring | 1.0 | Bearer, signal, addresses |
| 5 | Firmware Update | 1.0 | Package, Package URI, Update, State, Update Result |
| 6, 7 | Location, Connectivity Statistics | 1.0 | Position; traffic counters |
| 9 | Software Management | Registry | Install, uninstall and activate software packages |
| 21 | LwM2M OSCORE | 1.1 | OSCORE Master Secret, IDs, algorithms |
| 23, 24 | LwM2M COSE, MQTT Server | 1.2 | COSE keys; broker settings |
| 25 to 27 | Gateway, Gateway Routing, 5G-NR Connectivity | 1.2 | Devices behind gateways; 5G radio data |
Servers must support Security, Server and Device, and should support the other 1.0 objects.
Object ID ranges and the OMA registry
Objects beyond the core set are registered with OMNA, the OMA Naming Authority. Appendix D of the Core specification assigns the ranges:
| Class | URN segment | IDs | Used by |
|---|---|---|---|
| OMA | oma | 0 to 1023 | OMA |
| SDO | ext | 2048 to 10240 | Other standards bodies, including IPSO |
| Vendors | x | 10241 to 32768 | Vendors and individuals |
| Company reserved | x | 32769 to 42768 | Private objects, not published |
| Test | x | 42769 to 42800 | Testing only, never production |
The registry's XML gives each object a versioned URN. The IPSO Temperature object is urn:oma:lwm2m:ext:3303:1.1, for "a temperature sensor to report a temperature measurement"; Firmware Update is urn:oma:lwm2m:oma:5:1.2. Version mismatches change which resources exist, which is why the Core specification tells both sides not to treat unknown optional resources as errors.
Payloads can be plain text, opaque (used for firmware), CBOR, TLV, SenML JSON or CBOR (1.1), or LwM2M CBOR (1.2, CoAP content format 11544). Libraries make these build time choices; Wakaama exposes CMake options such as WAKAAMA_DATA_SENML_CBOR.
Which transports LwM2M defines, and where OSCORE fits
| Binding | Scheme and default port | Security | Since |
|---|---|---|---|
| CoAP over UDP | coap 5683, coaps 5684 | DTLS 1.2, optionally 1.3; or OSCORE | 1.0 |
| CoAP over SMS | MSISDN | DTLS or SIM secured packets | 1.0 |
| CoAP over TCP | coap+tcp 5683, coaps+tcp 5684 | TLS | 1.1 |
| LoRaWAN | lorawan scheme with FPort 1 to 255 | NoSec at LwM2M level; LoRaWAN security | 1.1 |
| 3GPP CIoT (NB-IoT, LTE-M), IP and non-IP | Appendix D | Cellular, DTLS or OSCORE | 1.1 |
| CoAP over WebSockets | coap+ws 80, coaps+ws 443 | TLS | Listed in the 1.2.2 Transport spec |
| HTTP | HTTP/1.1, optionally HTTP/2 | TLS | 1.2 |
| MQTT | 3.1.1 or 5 broker | TLS to broker | 1.2 |
Over UDP every operation must be a Confirmable CoAP message except Notify, Execute and Send. Firmware images use block-wise transfer (RFC 7959) and observations use the Observe option (RFC 7641).
OSCORE: security at the message level
OSCORE (RFC 8613, July 2019) protects each CoAP request and response with COSE. The RFC explains the point: with DTLS a proxy must terminate the channel and can read and change everything, while OSCORE gives end to end protection through proxies. The LwM2M Transport specification makes it optional for bootstrap and server traffic and notes it runs over UDP, TCP, SMS and non-IP links, including IEEE 802.15.4 and 3GPP CIoT. The mandatory algorithm is AES-CCM-16-64-128 with HMAC SHA-256. Keys live in object 21 (Master Secret, Sender ID, Recipient ID, optional algorithms, Master Salt and ID Context), linked from Security resource 17.
EDHOC (RFC 9528, March 2024) is the IETF's compact authenticated Diffie-Hellman exchange whose main use case, per the RFC, is establishing an OSCORE context with forward secrecy. The LwM2M 1.2.2 specifications do not reference it; they provision OSCORE from pre-shared Master Secrets. Check your libraries before assuming EDHOC support.
DTLS 1.3 and the Connection ID
CoAP over UDP uses DTLS 1.2 (RFC 6347). LwM2M 1.2 allows DTLS 1.3 (RFC 9147, April 2022) and says implementations should follow RFC 7925, the TLS and DTLS profile for IoT. Without a Connection ID (RFC 9146), a DTLS 1.2 session is tied to the peer's address and port, so a NAT rebinding after sleep forces a full handshake. Zephyr's docs recommend CONFIG_LWM2M_DTLS_CID, which they say "completely removes the handshake" on resume when the server supports it.
Which security modes exist, and what each one stores
The Transport specification requires every client and server to authenticate each other before exchanging data, all traffic to be encrypted and integrity protected, replay protection, freshness checks and secure fragmentation "in particular in the case of firmware updates". Bootstrap servers, servers and clients must use different key pairs, and client keys must be unique per client.
| Mode | Value | /0/x/3 Identity | /0/x/4 Server key | /0/x/5 Secret | Required suite (1.1 and later) |
|---|---|---|---|---|---|
| Pre-Shared Key | 0 | PSK identity | Unused | PSK | TLS_PSK_WITH_AES_128_CCM_8 |
| Raw Public Key | 1 | Client public key | Server public key | Private key | TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 |
| Certificate | 2 | Client certificate | Trust anchor or server certificate | Private key | TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 |
| NoSec | 3 | Unused | Unused | Unused | None |
| Certificate with EST | 4 | Unused | Server certificate | Generated on device | As Certificate mode |
Pre-Shared Key is smallest in code, RAM and airtime. The specification recommends keys of at least 16 bytes, supports up to 64, and forbids low entropy secrets or passwords. Clients should not use the CBC suite servers must also support. The risk is operational: the server's key store is as sensitive as the whole fleet.
Raw Public Key (RFC 7250) uses elliptic curve keys without certificates; each side must check the presented key exactly matches the stored one. Certificate mode uses X.509v3 profiled by RFC 7925, requires secp256r1 and forbids curves under 255 bits. Certificate Usage (/0/x/15) says whether the server key is a CA constraint (0), service certificate (1), trust anchor (2) or domain issued certificate (3, the default). Certificates need a trusted clock, and the specification calls writes to the Device Current Time resource security critical. It also "does not offer a way to recover from an expired Bootstrap-Server certificate" or a revoked one; recovery is out of band, for example a new trust anchor in a firmware update.
Certificate with EST, added in 1.1, has the device generate its own key pair and enrol over EST-coaps (RFC 9148, April 2022, a constrained profile of RFC 7030), proving possession with a PKCS#10 request. In the specification's words, "The private key therefore never leaves the LwM2M Device." The cost is extra enrolment messages.
NoSec applies no DTLS, TLS or OSCORE. The specification says LwM2M "MUST NOT be deployed without appropriate security"; NoSec deployments must rely on another layer and the server must match the endpoint name to the network access identity. LoRaWAN's binding is NoSec because LoRaWAN secures frames itself. On plain IP, NoSec means readable, modifiable CoAP on port 5683.
The endpoint name is not an identity
The endpoint client name in Register and Bootstrap-Request is "not authenticated at the application layer". The server must compare it with the DTLS or TLS identity and answer 4.00 Bad Request on mismatch. Skip that and any valid device can register as any other.
Freshness and the Echo option
DTLS and OSCORE reject duplicates but accept reordered messages inside their replay windows, so a Write delayed by an attacker could later overwrite a newer one. The specification points to the CoAP Echo option (RFC 9175): the client answers with a nonce and the server repeats the request carrying it. Use it for clock changes, update triggers and access control writes.
How the bootstrap server provisions credentials
The Core specification defines four bootstrap modes: Factory (written at manufacture), Smartcard (read from a SIM over a GlobalPlatform secure channel), Client Initiated (the client contacts a preloaded bootstrap account), and Server Initiated (an authorised server executes the Bootstrap-Request Trigger, /1/x/9). Clients must try smartcard and factory data first. Both bootstrap server modes need preloaded DTLS, TLS or OSCORE credentials, so bootstrapping moves the trust problem rather than removing it: the factory still installs one credential per device, and it anchors everything the device later trusts.
| Step | Direction | Operation | Effect |
|---|---|---|---|
| 1 | Client to Bootstrap-Server | Secure handshake | Mutual authentication with bootstrap credentials |
| 2 | Client to Bootstrap-Server | Bootstrap-Request with endpoint name | Asks to be configured |
| 3 | Bootstrap-Server to Client | Bootstrap-Discover (optional) | Lists objects, Security instances and Short Server IDs |
| 4 | Bootstrap-Server to Client | Bootstrap-Delete (optional) | Removes stale accounts; never the bootstrap account or Device object |
| 5 | Bootstrap-Server to Client | Bootstrap-Write, repeated | Writes Security, Server and, as needed, OSCORE, COSE, MQTT Server and Access Control instances |
| 6 | Bootstrap-Server to Client | Bootstrap-Finish | Ends the session; client checks consistency |
| 7 | Client to Server | Handshake, then Register | Connects with the new credentials |
LwM2M 1.2's Bootstrap-Pack-Request fetches the whole configuration in one response, cutting messages on NB-IoT and LoRaWAN.
A server account is a Security and a Server instance sharing a Short Server ID (1 to 65534). Three bootstrap account resources deserve deliberate values:
- Client Hold Off Time (/0/x/11) delays client initiated bootstrap, spreading a fleet's retries after an outage.
- Bootstrap-Server Account Timeout (/0/x/12) makes the client purge the bootstrap account after that many seconds; 0 or absent means forever. A finite value stops a stolen device being re-bootstrapped later, but you then need another re-provisioning path.
- Last Bootstrapped (/1/x/12) records when an account was last updated.
Deleting a Security instance also deletes its Server instance, objects only that server could reach and its observations. Keys changed during an open DTLS session are not picked up automatically; whether to close the session is a local policy decision to make before rotating keys.
How the Firmware Update object works
| ID | Resource | Ops | Meaning |
|---|---|---|---|
| 0 | Package | W | Image pushed by block-wise Write |
| 1 | Package URI | RW | Where the client pulls the image |
| 2 | Update | E | Install; only in Downloaded state |
| 3 | State | R | 0 Idle, 1 Downloading, 2 Downloaded, 3 Updating |
| 5 | Update Result | R | 0 to 11 |
| 6, 7 | PkgName, PkgVersion | R | Package name and version |
| 8 | Protocol Support | R | 0 CoAP, 1 CoAPS, 2 HTTP 1.1, 3 HTTPS 1.1, 4 CoAP over TCP, 5 CoAP over TLS |
| 9 | Delivery Method | R | 0 pull, 1 push, 2 both |
| 10 | Cancel | E | Cancel before installation |
| 11 | Severity | RW | 0 Critical, 1 Mandatory, 2 Optional |
| 13 | Maximum Defer Period | RW | 0 means no deferral |
| 14 | Automatic Upgrade at Download | RW | Install as soon as downloaded |
The state machine
- Idle (0). The server writes Package or Package URI and the state moves to Downloading.
- Downloading (1). Errors go only to Update Result: 2 not enough flash, 3 out of RAM, 4 connection lost, 7 invalid URI, 9 unsupported protocol. Writes to Package URI here should be rejected.
- Downloaded (2). The server executes /5/0/2, or the client proceeds alone if Automatic Upgrade at Download is true. A user deferral keeps this state with result 11.
- Updating (3). Success returns to Idle with result 1. Failure returns to Downloaded or Idle; integrity failure (5) goes to Idle and the image should be deleted. Other results are 6 unsupported package type, 8 failed and 10 cancelled.
Writing an empty Package URI resets to Idle with result 0. Afterwards the server reads /3/0/3 or /5/0/7 to confirm the running version. If new firmware drops an object, the client must delete its instances, so expect the registration to change.
Worked example: messages per push
The Core specification's example pushes an 80 KiB image (81,920 bytes) in 128 byte blocks: 81,920 / 128 = 640 Confirmable messages. With 1,024 byte blocks, the CoAP maximum, it takes 80; with 512 bytes, 160. On high latency links block size decides whether an update takes minutes or hours, and client buffer size caps the block. Wakaama's WAKAAMA_COAP_RAW_BLOCK1_REQUESTS option exists so low memory clients can handle large writes, "typically a firmware write". For pull delivery, the specification says "a CoAP server implementing block-wise transfer is sufficient" as the file server, and the server must only offer schemes the client lists in /5/0/8.
What the Firmware Update object does not do: signing
Update Result 5 shows the client checked something, but LwM2M does not define the image format, signature algorithm, verifying key or downgrade rule. The secure channel, which the Transport specification extends to the firmware repository in Package URI, proves where bytes came from, not who built them. If an attacker controls the management server or the file host, DTLS will faithfully deliver their image. Signing must be enforced by the device's boot and update code, with the public key in protected storage and a version counter that refuses downgrades.
SUIT manifests
The IETF SUIT working group fills that gap. RFC 9019 (April 2021) is the architecture; its abstract says IoT vulnerabilities "have raised the need for a reliable and secure firmware update mechanism" and argues for a transport agnostic manifest. RFC 9124 (January 2022) is the information model. The CBOR format, draft-ietf-suit-manifest, was at revision 37 in the RFC Editor queue when we checked the Datatracker in October 2026.
| RFC 9124 element | Requirement | Stops |
|---|---|---|
| Monotonic sequence number | REQ.SEC.SEQUENCE | Rollback to an older image; must never wrap |
| Vendor ID and Class ID | REQ.SEC.COMPATIBLE | Firmware for the wrong device type |
| Expiration time | REQ.SEC.EXP | Stale updates |
| Manifest signature | REQ.SEC.AUTHENTIC | Images the expected signer did not authorise |
| Whole image digest | REQ.SEC.IMG.COMPLETE_DIGEST | Swapped or altered payloads |
| Payload encryption (optional) | REQ.SEC.IMG.CONFIDENTIALITY | Reading the image |
LwM2M delivers the signed manifest and payload and triggers Update; the device verifies signature, digest, sequence and class before writing, and reports result 5 or 6 on failure. The management server can then tell a device to update but cannot make it run anything your signing key did not authorise.
LwM2M, TR-069 and MQTT based device management compared
| LwM2M 1.2 | TR-069 (CWMP) | Ad hoc over MQTT | |
|---|---|---|---|
| Owner | OMA SpecWorks | Broadband Forum | Your team |
| Typical devices | Constrained sensors, meters, trackers | Home gateways, set top boxes | Anything with an MQTT client |
| Transport | CoAP over UDP, TCP, SMS, LoRaWAN, CIoT; HTTP; MQTT | SOAP over HTTP | MQTT over TCP or WebSockets |
| Data model | Registered numbered objects, CBOR and SenML | XML parameter trees (TR-181) | Your own topics and schemas |
| Security | DTLS or TLS with PSK, RPK, X.509 or EST; OSCORE | TLS and HTTP authentication | TLS to broker plus broker ACLs |
| Provisioning | Bootstrap server, factory, smartcard, EST | ACS configuration | Custom |
| Firmware | Object 5 states and results; object 9 for software | Download RPC | Custom |
| Fit | Multi vendor constrained fleets | Operator managed CPE | Small single vendor fleets |
Implementations you are likely to find
Eclipse Leshan is a Java LwM2M server and client, an Eclipse project since 2014, built on the Californium CoAP and Scandium DTLS libraries, with server, client and bootstrap server demos and releases on Maven Central. Its README lists 1.x (Java 7) as stable and 2.x on master (Java 8). It is dual licensed EPL-2.0 or BSD-3-Clause. Its public sandbox servers are for evaluation only.
Eclipse Wakaama (formerly liblwm2m) is a C library built with CMake as client, server or bootstrap server, with a tinydtls transport option. Its README says the only official release, 1.0 (December 2018), "is affected by various security issues", is unsupported, and users should track the main branch. The GitHub repository was archived on 15 September 2026, and the Eclipse project page lists it as Archived. Vendored Wakaama code now has no upstream for fixes.
Zephyr RTOS ships a LwM2M client (CONFIG_LWM2M) implementing 1.0.2 by default and 1.1.1 optionally, with the core objects plus IPSO objects. With CONFIG_LWM2M_DTLS_SUPPORT it uses DTLS in PSK or X.509 mode, reading keys from object 0. Its own sample code comments "3 = NoSec mode (no security beware!)".
Cellular modules often embed a LwM2M client in modem firmware; fixes for those come from the module vendor.
Step by step: inventory and harden a LwM2M fleet
None of these steps write to a device. Run anything on production networks only with the fleet owner's approval.
1. Find every LwM2M client and server in your code
# Java servers: Leshan and Californium versions
mvn dependency:tree -Dincludes=org.eclipse.leshan,org.eclipse.californium
./gradlew dependencies --configuration runtimeClasspath | grep -E "leshan|californium"
# Zephyr firmware: final Kconfig values after a build
grep -E "^CONFIG_(LWM2M|MBEDTLS_PEM)" build/zephyr/.config
# C firmware that vendors Wakaama or similar code
git submodule status --recursive | grep -i -E "wakaama|lwm2m"
grep -rIl --include=*.h -E "LWM2M_CLIENT_MODE|lwm2m_context_t" . | head
Record per product: library, version or commit, LwM2M version, objects, transports and compiled in security modes. Flag any Wakaama based code and assign an owner for its fixes.
2. Check each device's security mode
The management interface cannot read object 0, so count modes (/0/x/2) from the bootstrap server's records. Any mode 3 device on an IP binding is a finding unless a documented link layer control covers it. On a lab or staging network you own, confirm passively:
# Read only: plaintext CoAP on 5683 means NoSec, DTLS on 5684 means a secured mode
sudo tcpdump -n -i eth0 -c 200 'udp port 5683 or udp port 5684'
tshark -r lwm2m.pcap -Y coap -T fields -e ip.src -e coap.opt.uri_path | sort | uniq -c
Readable paths such as rd (registration) or bs (bootstrap) mean devices register without LwM2M security. In staging, also present one device's name with another's credentials and confirm the server returns 4.00 Bad Request.
3. Require signed firmware
- Verify the update path checks a signature before writing, keeps the public key in protected storage and refuses lower versions.
- Offer only CoAPS, HTTPS or CoAP over TLS Package URIs, matching /5/0/8.
- Limit write access on the image host to your release pipeline and keep signing keys off the LwM2M Server.
- Set Severity and Maximum Defer Period so critical fixes cannot be deferred forever.
- After rollout, compare /3/0/3 or /5/0/7 with the expected version and investigate devices stuck in Downloaded or reporting result 5.
4. Rotate bootstrap and server credentials
- Replace fleet wide PSKs with per device keys, then move to Raw Public Key, Certificate or EST where hardware allows.
- Rotate server keys with Server Initiated Bootstrap via /1/x/9, deciding first whether open sessions close.
- Set Bootstrap-Server Account Timeout where another re-provisioning path exists, and plan bootstrap trust anchor replacement before expiry.
- Keep the bootstrap server off the public internet where the bearer allows (private APN or VPN) and alert on unknown endpoint names.
Common mistakes
- NoSec left on in production. Development builds use mode 3 on 5683; make the release build fail if NoSec is compiled in for an IP binding.
- One PSK for the whole fleet. The specification requires unique keys. One extracted key then impersonates every device.
- Low entropy keys. Serial numbers or MAC addresses as PSKs break the explicit rule. Use at least 16 random bytes.
- Firmware URIs without signature checks. DTLS protects transfer, not authorship.
- No downgrade protection. A signed old image is still a vulnerable image.
- A bootstrap server reachable from the internet. It can rewrite every device's servers and keys. Treat it like a certificate authority.
- Trusting the endpoint name. Bind it to the DTLS or OSCORE identity.
- Ignoring time. Restrict writes to /3/0/13 with Access Control and check freshness.
- Forgetting vendored libraries. A client compiled into firmware years ago still runs, even after its upstream is archived.
FAQ
What is LwM2M used for?
Managing constrained IoT devices remotely: identifying them, reading sensors, changing configuration, rotating credentials and delivering firmware. It is common on NB-IoT and LTE-M devices, smart meters and trackers.
Is LwM2M the same as CoAP?
No. CoAP (RFC 7252) is the transfer protocol. LwM2M adds the object model, bootstrap and registration, defined operations and standard objects, and 1.2 can also run over HTTP and MQTT.
Which LwM2M version should I use?
1.2.2 (June 2024) is current. Servers should support older clients of the same major version, but check what your client library implements; some default to 1.0.2.
What port does LwM2M use?
UDP 5683 for unsecured CoAP and 5684 for CoAP over DTLS; TCP uses the same numbers for coap+tcp and coaps+tcp. Production IP devices belong on 5684.
What is the LwM2M bootstrap server?
The server that writes server accounts and keys into a device using Bootstrap-Write, Bootstrap-Delete and Bootstrap-Finish. It is the only party that can change the Security object.
Does LwM2M support certificates?
Yes. Mode 2 uses X.509, and mode 4 (from 1.1) lets the device generate its key and enrol with EST over CoAP, so the private key never leaves the device.
How does LwM2M firmware update work?
The server writes an image to /5/0/0 or a URI to /5/0/1, the device goes Idle, Downloading, Downloaded, the server executes /5/0/2, and the device goes Updating then Idle, reporting the outcome in /5/0/5.
Does LwM2M sign firmware images?
No. Signature checks, downgrade protection and image format belong to the device's update code, often a bootloader's signed image format or SUIT manifests (RFC 9019, RFC 9124).
What is the difference between OSCORE and DTLS in LwM2M?
DTLS secures each hop, so proxies see the traffic. OSCORE protects each request and response end to end, works through proxies and over non-IP links, and is configured in object 21.
Is Eclipse Wakaama still maintained?
Its GitHub repository was archived on 15 September 2026 and the Eclipse project is listed as archived. Teams shipping Wakaama based code must maintain it themselves or migrate.
Where Safeguard fits
Safeguard does not manage IoT devices, run LwM2M or bootstrap servers, provision device keys, analyse firmware images or inspect CoAP traffic, and none of the steps above depend on it. The honest connection is the software your team builds around a deployment: management and bootstrap services on Leshan and Californium, integration services that consume device data, and the container images they ship in.
For that software, Safeguard's software composition analysis inventories your dependencies, container scanning shows which images carry which package versions, and SBOM generation records the result in SPDX or CycloneDX. The platform shows which projects contain a given component version, vulnerability matching and reachability analysis help you prioritise, and policies and gates can stop a build that pulls in a known vulnerable version. See using SBOMs to find affected products fast. Firmware on the devices is fixed through your own signed update pipeline or the module vendor's releases.
Every LwM2M server, bootstrap service and integration job you run pulls open source protocol libraries through the same package managers and base images as any other service. Keeping those dependencies current is the part of IoT device management security that sits in your own build pipeline.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.
3. Gold Registry: start from components that are already fixed
Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | Safeguard policies and gates in CI |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
These demos show dependency, SBOM and remediation workflows for services you build, not device management or firmware analysis. You can download Safeguard and follow the CLI docs to try them.
This demo sets up the Safeguard runner on your own machine, approves it with its device code and scans from the terminal. Pointed at a LwM2M management service or its container image, the same scan lists the packages inside, including CoAP and DTLS libraries, and their known vulnerabilities.
Click through it at your own pace, or open it full screen.
This demo is a real CLI session: asked to fix the lodash CVE in a repository, it reads the finding and advisory, asks before any command that changes something, moves lodash to 4.17.21, runs npm install and npm test with your approval, and pushes nothing. The same flow applies when you bump a CoAP or LwM2M library in a service that manages your devices.
Click through it at your own pace, or open it full screen.
This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. You can then ask which projects ship a given Leshan or Californium release and get the answer from your own scan data.
Click through it at your own pace, or open it full screen.
Quick check
Your LwM2M server is compromised. Can the attacker read device DTLS keys through the management interface?
No. Clients must reject management and reporting operations on the Security (0), OSCORE (21) and COSE (23) objects; only the bootstrap interface reaches them. The attacker could still push firmware, which is why devices must verify image signatures themselves.
All devices use DTLS on 5684 and firmware arrives over CoAPS. Is the update path secure?
Not necessarily. DTLS proves the image came from your server or file host unaltered, not that your release process built it. Without on device signature and downgrade checks, whoever controls the server or host controls the fleet, and a fleet wide PSK lets one extracted key impersonate any device.
Sources
- OMA: What is LwM2M
- OMA: LwM2M versions
- OMA: LwM2M enablers
- LwM2M Core 1.2.2
- LwM2M Transport 1.2.2
- OMNA LwM2M registry
- Registry: object 3303
- Registry: object 9
- Eclipse Leshan
- Leshan on GitHub
- Wakaama on GitHub
- Wakaama project page
- Zephyr LwM2M
- RFC 7252 CoAP
- RFC 6347 DTLS 1.2
- RFC 9147 DTLS 1.3
- RFC 9146 DTLS Connection ID
- RFC 7925 IoT TLS profile
- RFC 7250 Raw Public Keys
- RFC 8613 OSCORE
- RFC 9528 EDHOC
- RFC 7030 EST
- RFC 9148 EST-coaps
- RFC 9175 CoAP Echo
- RFC 8323 CoAP over TCP
- RFC 7959 Block-wise
- RFC 7641 Observe
- RFC 9019 SUIT architecture
- RFC 9124 SUIT information model
- draft-ietf-suit-manifest
- TR-069 Amendment 6 Corrigendum 1
- Broadband Forum CWMP data models
Last reviewed: 25 October 2026. LwM2M, SUIT and the implementations above keep evolving; check the linked pages for the versions your devices and servers run.