diff --git a/src/main/agent-hooks/server/server-ingest-remote.ts b/src/main/agent-hooks/server/server-ingest-remote.ts index f356d97e58f..c8eefeb1a50 100644 --- a/src/main/agent-hooks/server/server-ingest-remote.ts +++ b/src/main/agent-hooks/server/server-ingest-remote.ts @@ -24,6 +24,7 @@ import { } from '../../../shared/agent-status-legacy-adapter' import { isValidPiProviderSessionOnly } from './server-status-identity' import { AgentHookServerIngestStructured } from './server-ingest-structured' +import { parseAgentStatusReportedExecutionBinding } from '../../../shared/agent-status-execution-binding' export abstract class AgentHookServerIngestRemote extends AgentHookServerIngestStructured { /** Ingest a payload from the relay JSON-RPC channel (not the local HTTP server); connectionId is stamped here. Main is still the SSH trust boundary, so re-run the canonical normalizer before caching. */ @@ -271,7 +272,10 @@ export abstract class AgentHookServerIngestRemote extends AgentHookServerIngestS paneKey, source, launchToken: statusDisposition === 'restart' ? undefined : envelope.launchToken, - reportedExecutionBinding: envelope.reportedExecutionBinding, + // Parsed here, not trusted: every sibling field on this envelope is re-validated because the + // relay crosses a trust boundary, and the WSL relay reaches this with a raw wire cast. + reportedExecutionBinding: + parseAgentStatusReportedExecutionBinding(envelope.reportedExecutionBinding) ?? undefined, tabId, worktreeId, connectionId: trimmedConnectionId, diff --git a/src/main/daemon/pty-subprocess/spawn-environment.ts b/src/main/daemon/pty-subprocess/spawn-environment.ts index cbace940f46..d98d08d35a1 100644 --- a/src/main/daemon/pty-subprocess/spawn-environment.ts +++ b/src/main/daemon/pty-subprocess/spawn-environment.ts @@ -18,13 +18,8 @@ import { } from '../../../shared/windows-environment-expansion' import type { TuiAgent } from '../../../shared/tui-agent' import type { PtySubprocessOptions } from '../pty-subprocess' +import { PANE_IDENTITY_ENV_KEYS } from '../../../shared/pane-identity-env' -const PANE_IDENTITY_ENV_KEYS = [ - 'ORCA_PANE_KEY', - 'ORCA_TAB_ID', - 'ORCA_WORKTREE_ID', - 'ORCA_AGENT_LAUNCH_TOKEN' -] as const const WINDOWS_PATH_ENV_KEY_RE = /^path$/i function composeGuardedDaemonGitConfigEnv( diff --git a/src/main/providers/local-pty-launch-helpers.ts b/src/main/providers/local-pty-launch-helpers.ts index b82e6a32bbb..fdc2ee0b5b4 100644 --- a/src/main/providers/local-pty-launch-helpers.ts +++ b/src/main/providers/local-pty-launch-helpers.ts @@ -4,15 +4,7 @@ import { parseWslPath } from '../wsl' import { resolvePathEnvKey } from '../pty/windows-environment-path' import { expandWindowsEnvironmentVariables } from '../../shared/windows-environment-expansion' import { resolveSafePtyDefaultCwd } from './pty-default-cwd' - -const PANE_IDENTITY_ENV_KEYS = [ - 'ORCA_PANE_KEY', - 'ORCA_TAB_ID', - 'ORCA_WORKTREE_ID', - 'ORCA_AGENT_LAUNCH_TOKEN', - 'ORCA_AGENT_STATUS_RUN_ID', - 'ORCA_AGENT_STATUS_EXECUTION_ID' -] as const +import { PANE_IDENTITY_ENV_KEYS } from '../../shared/pane-identity-env' export function getDefaultCwd(): string { return resolveSafePtyDefaultCwd() diff --git a/src/shared/claimed-agent-pty-owner-promotion.ts b/src/shared/claimed-agent-pty-owner-promotion.ts index 09042a24567..4b1b498bd9c 100644 --- a/src/shared/claimed-agent-pty-owner-promotion.ts +++ b/src/shared/claimed-agent-pty-owner-promotion.ts @@ -1,4 +1,3 @@ -import type { AgentSessionClaimedSpawnResult } from './agent-session-host-authority' import type { AgentStatusExecutionBinding } from './agent-status-execution-binding' import { agentSessionSurfacesEqual, @@ -10,6 +9,7 @@ import { type LiveAgentSessionOwner } from './claimed-agent-pty-owner-snapshot' import type { + AgentSessionClaimedSpawnResult, AgentSessionExecutionClaim, AgentSessionSurfaceBinding } from './agent-session-host-authority' diff --git a/src/shared/pane-identity-env.ts b/src/shared/pane-identity-env.ts new file mode 100644 index 00000000000..237a7f91ddc --- /dev/null +++ b/src/shared/pane-identity-env.ts @@ -0,0 +1,15 @@ +/** + * Environment variables that name which pane and which launched execution a PTY belongs to. + * + * A pane that did not request these must not inherit them from the spawning process, so every + * spawn path scrubs the same list. It lives here because the local provider and the daemon each + * scrub independently, and a key added to one list and not the other stops being scrubbed at all. + */ +export const PANE_IDENTITY_ENV_KEYS = [ + 'ORCA_PANE_KEY', + 'ORCA_TAB_ID', + 'ORCA_WORKTREE_ID', + 'ORCA_AGENT_LAUNCH_TOKEN', + 'ORCA_AGENT_STATUS_RUN_ID', + 'ORCA_AGENT_STATUS_EXECUTION_ID' +] as const