Add opt-in WebSocket authentication to exec-server (#47601)

## What changed

Expose the shared `--ws-auth` options on `codex exec-server` for direct WebSocket listeners. Support capability tokens configured by token file or SHA-256 digest, and signed JWT bearer tokens. Validate `Authorization: Bearer TOKEN` before each WebSocket upgrade, rejecting missing or invalid credentials with HTTP 401 when authentication is enabled.

Reject listener authentication with stdio, `--remote`, or `forward`. Document the options and connection-time authentication behavior.

## Testing

Add CLI integration tests for all three credential configurations, unauthorized upgrade rejection, authenticated RPC initialization and reconnects, invalid configuration, and incompatible transports.

GitOrigin-RevId: 941fbd3d43e732c910d29b6f8137077b7c332835
This commit is contained in:
Ruslan Nigmatullin
2026-09-23 17:56:46 +00:00
committed by copyberry
parent 6824dabe03
commit 2210190435
10 changed files with 315 additions and 13 deletions
+9
View File
@@ -23,6 +23,7 @@ use codex_login::is_workload_identity_selected;
use codex_login::read_codex_access_token_from_env;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_cli::CliConfigOverrides;
use codex_websocket_auth::WebsocketAuthArgs;
use crate::exec_server_auth;
use crate::exec_server_telemetry;
@@ -58,6 +59,9 @@ pub(super) struct ExecServerCommand {
)]
listen: Option<String>,
#[command(flatten)]
websocket_auth: WebsocketAuthArgs,
/// Register this exec-server as a remote environment using the given base URL.
#[arg(
long = "remote",
@@ -147,6 +151,10 @@ impl ExecServerCommand {
) -> anyhow::Result<()> {
let strict_config = self.strict_config;
self.validate_remote_transport()?;
let websocket_auth = self.websocket_auth.try_into_settings()?;
if websocket_auth.config.is_some() && (self.remote.is_some() || self.command.is_some()) {
anyhow::bail!("WebSocket listener auth cannot be used with --remote or forward");
}
let codex_self_exe = arg0_paths
.codex_self_exe
.clone()
@@ -279,6 +287,7 @@ impl ExecServerCommand {
telemetry,
http_client_factory,
self.request_dispatch_mode,
websocket_auth,
),
exec_server_telemetry::ParentLifetime::Independent,
exec_server_telemetry::ShutdownBehavior::Immediate,