Blog Behind the Magic
Behind the Magic

Security postmortem

How a missing session looked like a valid one

On August 3, 2026, a security researcher reported a critical vulnerability in Homey through our coordinated disclosure process. A flaw in how the local devkit connection validated app sessions could let an attacker on the same network gain control of a Homey. If port forwarding was enabled, an attacker could also do this from the internet.

We shipped the fix in v13.4.1 for Homey Pro and Homey Self-Hosted Server on August 18 and notified affected users on August 20. We searched our own logs and found no evidence that the vulnerability was exploited.

We promised a write-up once people had had a chance to update. The fix has now been out for weeks and adoption is high, so we can share what happened. Because some Homeys are still on older versions, we explain the problem without giving enough detail to reproduce the attack.

Impact

The vulnerability allowed an unauthenticated attacker to control a Homey. That includes control over cameras, locks, doors, and every other connected device. An attacker could also access the settings of installed apps, which can hold tokens and passwords.

Reachability depended on the network. On the local network, it was always reachable from any other device. From the internet, it was only reachable if the user had set up port forwarding to their Homey. Our cloud relay was not an exploitation path, and Homey Cloud was not affected, because it handles devkit sessions differently.

After building the fix, we searched our logs and telemetry for the fingerprint this attack would leave behind. We found no trace of it. As far as we can tell, the researcher found this before anyone else did.

As of October 20, 2026, 98% of affected Homeys seen online in the last 30 days are on v13.4.1 or newer. We exclude devices that have been offline longer because a Homey that is switched off cannot be attacked or updated and would only distort the number downward. The large majority of users were protected within days through automatic updates.

What went wrong

Homey apps run in a sandbox and talk to the core over the local devkit connection. Every message from an app is supposed to carry proof that it comes from a running, authenticated session. The bug was in how that proof was checked, and it came down to three weaknesses.

A missing session looked like a valid one. An app that has not started yet has no session assigned. Because of how the check was written, that “no session” state was accepted as if it were a real match. An attacker who presented an equally empty session passed the check.

The connection was trusted before it was verified. The incoming connection was associated with a real app before the session was validated, so by the time the check ran, the connection was already bound to that app.

A malformed message could crash the process. The handler read fields from an incoming message without first checking that the message was well formed. A deliberately broken message crashed the process. A crash forces a restart, and during a restart, apps have not started yet. In that state, the missing-session weakness could be used.

Chained together, these turned an unauthenticated connection into control of the Homey.

The fix

The fix in v13.4.1 addresses each of the three weaknesses, in the same order as above.

Only a real session is accepted. A valid session is now strictly defined. An empty or missing session is rejected rather than treated as a match.

The session is verified before the connection is trusted. The connection is now associated with an app only once the session is validated.

Malformed messages are rejected. Every incoming message is validated before anything is read from it. A malformed message is cleanly rejected instead of crashing the process, which removes the restart trick that opened the window.

We also added rate limiting so the restart window cannot be hammered. New tests send malformed and empty input through the session and message checks, so this class of bug gets caught if it reappears.

The reusable lesson

If you run any service that authenticates each message over a socket, three habits would have prevented this.

Treat a missing credential as hostile, not as a default. A default value that is also a legal input will pass the check. Define what a valid credential looks like and reject everything else, including null and empty values.

Establish state only after authentication. Binding a connection to an identity before verifying that identity was the core of this bug.

Validate the shape of input before you read its fields. Reading from an attacker-controlled message before checking it can crash the process.

How we handled it

The report reached us on August 3 at pentest@athom.nl, the address we publish for security reports. The researcher reported the issue privately, gave us time to fix it, and worked with us on when to disclose it.

  • August 3: report received.
  • August 5–6: root cause confirmed, fix and hardening built.
  • August 18: v13.4.1 released for Homey Pro and Homey Self-Hosted Server.
  • August 20: direct email to owners still on an older version, with update steps.
  • October 20: this postmortem.

The time between building the fix and shipping it went into our regular release process: alpha and beta releases, testing, and four release candidates before going to production.

We also weighed the legal side. The EU Cyber Resilience Act’s mandatory reporting obligations did not take effect until September 11, 2026, after this vulnerability had already been fixed and affected users notified. Even if they had applied, reporting would only have been mandatory for actively exploited vulnerabilities, and our investigation found no evidence of exploitation.

We do have a duty of care toward affected users, though, so we chose to get ahead of the issue: ship the fix, let auto-update carry most of the load, email the users still exposed, and then publish this.

We did not request a CVE for this vulnerability. It was reported privately, fixed in a coordinated release, and remediated through auto-update before public disclosure, so we handled disclosure through this postmortem.

We compensated the researcher for this report. The amount scales with the impact of the finding and the quality of the report, and this one scored high on both.

Why auto-update matters

Most Homey owners were protected without doing anything, because their Homey updated itself within days of the release. The owners we emailed were the ones who had turned off automatic updates. That is why we recommend leaving automatic updates on. A security fix protects you only once it is installed.

What we learned

What went well

Coordinated disclosure worked as it should. The researcher reached us through the right channel, we confirmed and fixed the root cause within days, and we could push the fix to most devices automatically.

What we got wrong

The bug came down to three mistakes: accepting an empty default as a valid session, trusting a connection before verifying it, and reading input before validating it. Mistakes like this are easy to make, and easy to miss in code that has worked for years.

Where we are improving

We have added tests around these paths, and we are reviewing other parts of the system with the same three questions: whether empty credentials are rejected, whether state is set only after authentication, and whether input is validated before it is read.

Credits

Our thanks to Wesley Neelen of forsec.nl for finding this, reporting it responsibly, and documenting it clearly.

Report a security issue

If you believe you have found a security issue in Homey, please report it to pentest@athom.nl.

Stay in the loop with the latest from Homey.

Subscribe to our newsletter and stay up to date on new features, exclusive offers, and smart home inspiration.