daemon, client-core: keymap-command origin variables leak into launched processes #223

Closed
opened 2026-10-21 20:02:41 +09:00 by natsukium · 0 comments
Owner

Problem

The keymap-command origin variables (FELIS_ORIGIN_SESSION_ID, FELIS_HOST, FELIS_CWD, and the viewport anchors FELIS_INPUT_LINE_NUMBER, FELIS_CURSOR_LINE, FELIS_CURSOR_COLUMN) describe one chord, but nothing removes them from an inherited environment. child_env in crates/felis-client-core/src/pipe.rs only adds the values the current origin has, and the daemon's apply_env_policy (crates/felis-daemon/src/lib.rs) does not scrub them.

So a felis process launched from a keymap command carries the chord's values onward:

  • run from a --host window → the command launches a local felis window → that client's env (and its env_base snapshot) holds the old FELIS_HOST → a later chord from a local session in the new window, which has no host, still sees FELIS_HOST=<remote>. A script that branches on it dials the wrong daemon.
  • The same applies to a stale FELIS_CWD when the new origin has no OSC 7, and to the anchors for run / unanchored regions, which keybindings.md documents as unset.
  • A plain shell session created from such a client also inherits them.

Today this needs a run command that backgrounds a window launch itself (felis &), so it is latent; background run (#224) makes it the ordinary path. Reasoned from the source; not reproduced in a window.

Proposed fix

Scrub where every session's environment is already finalized, then set only the current origin's values.

  • Daemon: a new ORIGIN_ENV list of the six names, removed in apply_env_policy next to ENV_DENYLIST. That function runs for every create whatever the base (EnvBaseSource::Request, Relay, Birth), so it covers a snapshot, the relay carrier's env, a daemon whose birth env carries them (including a systemd-run hand-off and the over-cap capture fallback). Unlike ENV_DENYLIST it is not part of RESERVED_ENV_KEYS, so SpawnArgs.env may still set them: the transient's child_env pairs are applied after the scrub and reach the command.
  • Client: any client-side spawn of a keymap command (background run, #224) env_removes the six before setting the current origin's values, independent of the env snapshot (which is None over its caps).

Rejected: scrubbing at the capture and at daemon_command only. The relay base and a systemd-run-handed-off daemon bypass both.

Tests

  • A create with each base source (request snapshot, relay env, birth env) carrying the six yields a session without them.
  • The same create with the six in SpawnArgs.env yields exactly those values (the transient path).
  • A client-side spawn from a client whose own env has them, for an origin with no OSC 7 on a local carrier, sees no FELIS_CWD / FELIS_HOST and the current FELIS_ORIGIN_SESSION_ID.

Cascade: docs/reference/keybindings.md (origin variables are never inherited), docs/explanation/security-model.md "Process and environment boundary" if it enumerates the scrubbed lists, CHANGELOG (Fixed).

## Problem The keymap-command origin variables (`FELIS_ORIGIN_SESSION_ID`, `FELIS_HOST`, `FELIS_CWD`, and the viewport anchors `FELIS_INPUT_LINE_NUMBER`, `FELIS_CURSOR_LINE`, `FELIS_CURSOR_COLUMN`) describe one chord, but nothing removes them from an inherited environment. `child_env` in `crates/felis-client-core/src/pipe.rs` only *adds* the values the current origin has, and the daemon's `apply_env_policy` (`crates/felis-daemon/src/lib.rs`) does not scrub them. So a felis process launched from a keymap command carries the chord's values onward: - `run` from a `--host` window → the command launches a local `felis` window → that client's env (and its `env_base` snapshot) holds the old `FELIS_HOST` → a later chord from a local session in the new window, which has no host, still sees `FELIS_HOST=<remote>`. A script that branches on it dials the wrong daemon. - The same applies to a stale `FELIS_CWD` when the new origin has no `OSC 7`, and to the anchors for `run` / unanchored regions, which keybindings.md documents as unset. - A plain shell session created from such a client also inherits them. Today this needs a `run` command that backgrounds a window launch itself (`felis &`), so it is latent; background `run` (#224) makes it the ordinary path. Reasoned from the source; not reproduced in a window. ## Proposed fix Scrub where every session's environment is already finalized, then set only the current origin's values. - **Daemon:** a new `ORIGIN_ENV` list of the six names, removed in `apply_env_policy` next to `ENV_DENYLIST`. That function runs for every create whatever the base (`EnvBaseSource::Request`, `Relay`, `Birth`), so it covers a snapshot, the relay carrier's env, a daemon whose birth env carries them (including a `systemd-run` hand-off and the over-cap capture fallback). Unlike `ENV_DENYLIST` it is **not** part of `RESERVED_ENV_KEYS`, so `SpawnArgs.env` may still set them: the transient's `child_env` pairs are applied after the scrub and reach the command. - **Client:** any client-side spawn of a keymap command (background `run`, #224) `env_remove`s the six before setting the current origin's values, independent of the env snapshot (which is `None` over its caps). Rejected: scrubbing at the capture and at `daemon_command` only. The relay base and a `systemd-run`-handed-off daemon bypass both. ## Tests - A create with each base source (request snapshot, relay env, birth env) carrying the six yields a session without them. - The same create with the six in `SpawnArgs.env` yields exactly those values (the transient path). - A client-side spawn from a client whose own env has them, for an origin with no `OSC 7` on a local carrier, sees no `FELIS_CWD` / `FELIS_HOST` and the current `FELIS_ORIGIN_SESSION_ID`. Cascade: `docs/reference/keybindings.md` (origin variables are never inherited), `docs/explanation/security-model.md` "Process and environment boundary" if it enumerates the scrubbed lists, CHANGELOG (Fixed).
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
felis-terminal/felis#223
No description provided.