An open redirect is usually reported as a phishing primitive. Here, the destination was only half the problem. The application deliberately added a controller connection string to the redirect, and that string contained the server's long-lived encryption key.
The affected company and product are intentionally omitted. Product names, versions, routes, message types, class names, and concrete protocol values have been generalized. The cryptographic and authorization failures are described in full.
A handoff endpoint trusted its destination
The self-hosted controller offered an onboarding handoff from its web interface to a companion client. A caller supplied the destination URL and a token. The server then built a redirect containing those values plus its own connection information.
// Simplified handoff logic
const handoff = {
controllerUrl: settings.connectionString()
};
redirect(`${deviceUrl}?${encode(handoff)}&token=${token}`);
The destination was not restricted to an approved scheme, host, or registered client. Supplying an attacker-controlled HTTPS URL made the server return a Location header pointed at that domain, with the controller-generated data intact.
The connection string contained a root secret
The serialized connection information was more than an address. It included a stable AES-256-GCM master key used by the controller's device protocol. Reading the redirect response—or simply following it—delivered that key to the attacker's server.
In isolation, including the key was an intentional part of the trusted client handoff. In isolation, the redirect was an input-validation issue. Together, the server exported its root device credential to an unauthenticated party in a single GET request.
Secrets embedded in a redirect inherit the trust policy of the destination. If the destination is arbitrary, the secret is public.
The device protocol trusted the same key
Managed devices connected to the controller over WebSocket. Known devices had individual encryption keys, but an unknown hardware address fell back to the global master key for its initial messages.
The upgrade path was rate-limited, but it did not require an enrollment token, client certificate, source allowlist, or proof that the device had been pre-registered. Possession of the leaked master key was enough to construct a valid encrypted introduction.
// Simplified server-side key selection
const device = await findDevice(message.hardwareAddress);
const key = device?.individualKey ?? controller.masterKey;
return decryptAndDispatch(message, key);
From unknown client to trusted device
- Call the onboarding endpoint with an attacker-controlled redirect destination.
- Extract the controller connection string and master key from the response.
- Connect to the public device WebSocket using a new synthetic hardware address.
- Encrypt a valid introduction with the leaked master key.
- Receive a newly minted per-device key and reconnect under that identity.
After the exchange, the forged client appeared in the controller's database as a trusted device. It could reach authenticated device RPC handlers and submit device-originated events. The proof demonstrated the boundary crossing with benign test data and controlled notifications, including attacker-supplied content delivered through administrator-facing channels.
Impact
The chain let a remote unauthenticated attacker join the controller's trusted device plane. That enabled persistent impersonation of a managed device, access to device-only operations, manipulation of controller state, and delivery of deceptive administrator notifications. The stable global key also expanded the lifetime of the compromise until rotation.
Fixing the handoff and enrollment protocols
Never put a root key in a redirect
The handoff should carry a short-lived, audience-bound, single-use enrollment code—not a long-lived controller secret. The receiving client can exchange that code over an authenticated channel.
Allowlist the destination
Normalize and compare the scheme and host against a small set of registered handoff destinations. Avoid substring, suffix, or user-info checks that can be confused by URL syntax.
Authenticate unknown devices explicitly
An unknown device should not be able to bootstrap solely with a controller-wide fallback key. Require pre-registration, a unique enrollment secret, a client certificate, or an operator-approved pairing flow.
Rotate and compartmentalize
Rotate the exposed master key and all credentials derived from it. Separate handoff, enrollment, and message-encryption keys so a failure in one protocol cannot authorize another.
Follow redirects as data flows, not only navigation. Enumerate every server-generated field appended to the destination, then trace each credential to every protocol that accepts it.
Closing thought
The redirect did not become critical because redirection itself was novel. It became critical because two independent onboarding systems shared the same root of trust. Understanding that relationship turned a small input bug into the real finding.
