Skip to content

[HOTFIX] Require random auth token for terminal WebSocket connections - #5434

Open
jongyoul wants to merge 4 commits into
apache:masterfrom
jongyoul:codex/security-terminal-auth-token
Open

[HOTFIX] Require random auth token for terminal WebSocket connections#5434
jongyoul wants to merge 4 commits into
apache:masterfrom
jongyoul:codex/security-terminal-auth-token

Conversation

@jongyoul

Copy link
Copy Markdown
Member

What is this PR for?

This PR hardens the %sh.terminal WebSocket endpoint by requiring a per-session 256-bit CSPRNG authentication token.

Previously, the terminal WebSocket server only validated the Origin request header, which could be forged by non-browser clients to interact with the interactive bash shell without credentials when the terminal port is reachable.

With this change:

  • TerminalInterpreter generates a 256-bit random authentication token using SecureRandom when creating the terminal server.
  • The token is passed to the frontend URL query string (?token=...) embedded in the paragraph result behind Zeppelin's note ACLs.
  • TerminalSocket validates the incoming token query parameter using constant-time MessageDigest.isEqual.
  • Connections without a valid token are immediately rejected with close code VIOLATED_POLICY (1008), and unauthenticated sessions ignore incoming messages.

What type of PR is it?

Hot Fix

Todos

  • Generate per-session auth token in TerminalInterpreter
  • Require and validate auth token in TerminalSocket
  • Pass token from dashboard iframe URL to WebSocket connection in index.js
  • Add unit test verifying that unauthenticated WebSocket connections without tokens are rejected

What is the Jira issue?

N/A

How should this be tested?

./mvnw test -pl shell -Dtest=TerminalInterpreterTest
./mvnw clean org.apache.rat:apache-rat-plugin:check -Prat -pl shell

Screenshots (if appropriate)

N/A

Questions:

  • Does the license files need to update? No
  • Is there breaking changes for older versions? No
  • Does this needs documentation? No

Copilot AI lite review requested due to automatic review settings August 24, 2026 00:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This hotfix hardens the %sh.terminal WebSocket endpoint by adding a per-terminal-server cryptographic auth token that clients must present via the WebSocket query string, preventing unauthenticated non-browser clients from connecting when the terminal port is reachable.

Changes:

  • Generate a 256-bit CSPRNG token in TerminalInterpreter and include it in the terminal dashboard URL.
  • Propagate the token from the dashboard URL into the WebSocket connection URL in the terminal frontend JS.
  • Enforce token validation in TerminalSocket and add a unit test for missing-token rejection.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
shell/src/test/java/org/apache/zeppelin/shell/TerminalInterpreterTest.java Updates test connections to include the token and adds a missing-token rejection test.
shell/src/main/resources/html/js/index.js Reads token from query params and includes it in the WebSocket URL.
shell/src/main/java/org/apache/zeppelin/shell/TerminalInterpreter.java Generates/stores the auth token and appends it to the dashboard URL; exposes token for tests.
shell/src/main/java/org/apache/zeppelin/shell/terminal/websocket/TerminalSocket.java Validates token on connect and rejects unauthorized sessions.
shell/src/main/java/org/apache/zeppelin/shell/terminal/TerminalThread.java Passes the expected auth token to the WebSocket endpoint via user properties.
Suppressed comments (1)

shell/src/main/java/org/apache/zeppelin/shell/terminal/websocket/TerminalSocket.java:79

  • Logging the full Session object here can leak the auth token (query string) into logs on successful connections. Log a non-sensitive identifier (e.g., sess.getId()) instead.
    authorized = true;
    LOGGER.info("Socket Connected: {}", sess);
    terminalService.onWebSocketConnect(sess);

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread shell/src/test/java/org/apache/zeppelin/shell/TerminalInterpreterTest.java Outdated
tbonelee
tbonelee previously approved these changes Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants