OpenHands 1.25.0 stops embedding the local session key

OpenHands 1.25.0 defaults local launchers to loopback and removes the session key from off-loopback HTML unless an operator opts in.

OpenHands v1.25.0 changes the default path that exposed its local session API key. The npm, npx, static-server, and ingress launchers bind to 127.0.0.1, and an explicit non-loopback bind serves the UI without the embedded key unless the operator opts into LAN key injection. This turns the LAN disclosure described in issue 16879 into an API-key entry flow.

OpenHands v1.25.0 key facts

  • GitHub published OpenHands v1.25.0 on 2026-10-06 at 2026-10-06T00:56:53Z.
  • Pull request 17007 merged into main on 2026-09-29 and is included in v1.25.0 as "keep local session keys off externally reachable listeners."
  • Local npm run dev, npx @openhands/agent-canvas, static-server, and ingress paths default to 127.0.0.1.
  • An off-loopback bind strips sessionApiKey from served HTML and marks authentication as required. An explicit LAN-session-key opt-in bypasses that stripping.
  • Docker is key-free by default. The documented opt-in pairs AGENT_CANVAS_ALLOW_LAN_SESSION_KEY=true with -p 127.0.0.1:8000:8000.
  • The release also includes Model Router settings with a "Run at conversation start" toggle and server-catalog tool selection for agent profiles. Pull request 17516 pins the Agent Server and TypeScript client to 1.53.0.

How OpenHands exposed session keys before v1.25.0

Issue 16879, opened on 2026-08-24, described the affected local stack. Vite used server.host: true, the static server defaulted to ::, and the ingress proxy called server.listen(port) without a host. The local mode also supplied a session key to the frontend.

The static response placed the key in window.__AGENT_CANVAS_SESSION_API_KEY__. A peer on the same network could request http://<host>:8000/, read the key from the unauthenticated HTML, and send it as X-Session-API-Key to the same ingress. The ingress forwarded /api and /sockets traffic to the agent-server. With the terminal tool available, that credential could be used to start conversations that run commands on the host.

The bug was not that the agent-server lacked a credential. The problem was that a local launcher delivered the credential to every client that could reach its frontend port.

How OpenHands 1.25.0 applies bind policy

Pull request 17007 merged on 2026-09-29. It puts the listener decision and the HTML key decision behind scripts/bind-host.mjs:

export const DEFAULT_BIND_HOST = "127.0.0.1";

export function isLoopbackBind(host) {
  if (!host) return true;
  const normalized = host.replace(/^\[|\]$/g, "");
  return (
    normalized === "localhost" ||
    normalized === "::1" ||
    /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(normalized)
  );
}

export function applySessionKeyPolicy({ host, sessionApiKey, authRequired, allowLanSessionKey }) {
  if (isLoopbackBind(host) || allowLanSessionKey) {
    return { sessionApiKey, authRequired: Boolean(authRequired), strippedSessionKey: false };
  }
  return { sessionApiKey: null, authRequired: true, strippedSessionKey: Boolean(sessionApiKey) };
}

The loopback check accepts localhost, IPv6 ::1, and IPv4 addresses in 127.0.0.0/8. A bind such as 0.0.0.0 is outside that set, so the UI asks for the API key instead of receiving it in the page. The policy preserves automatic key injection only for loopback or an explicit opt-in.

How OpenHands 1.25.0 handles Docker

Docker containers need to listen on their container interfaces so published ports can reach them. OpenHands therefore omits the session key from Docker HTML by default. The documented transparent-auth example opts in to key injection and publishes the host port on loopback:

docker run -it --rm \
  -p 127.0.0.1:8000:8000 \
  -e AGENT_CANVAS_ALLOW_LAN_SESSION_KEY=true \
  ghcr.io/openhands/agent-canvas:v1.25.0

If the port is published on a LAN or public interface, leave out that opt-in and enter the API key in the UI. The change separates two decisions that used to travel together: where the listener is reachable and whether the frontend receives a credential automatically.

What else changed in OpenHands v1.25.0

The security fix is one item in the release. OpenHands v1.25.0 also adds direct-prompt Model Router settings, including a "Run at conversation start" toggle. Agent profiles can choose tools from the server's catalog instead of relying on a Canvas-side list. Pull request 17516 merged on 2026-10-05 and pins the Agent Server and TypeScript client to 1.53.0 for that catalog-based editor.

Sources

Last verified: 2026-10-06.

Spotted an outdated or wrong claim? Agents can report it with evidence throughPOST /api/feedback; an editor checks every report. See llms.txt for the agent API.