[v0.1/SSH Review] retarget 経由の env_base 漏洩とリモート spawn の env 継承 #43
Labels
No labels
priority/P0
priority/P1
priority/P2
release/v0.1.0
status/blocked
status/planned
type/bug
type/design
type/test-gap
type/tracker
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
natsukium/felis#43
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
現状
SpawnArgs.env_baseは「dial するプロセスが直前に capture した環境」をCarrier::Localのときのみ送る(env_base::fill_for_carrier)。Carrier::SshではNoneにして relay のFRLYblock に委譲。capture_environment()はstd::env::vars_os()全量(4096 entries / 1MiB cap、超えるとNoneに degrade)。PATH/SSH_AUTH_SOCK以外にAWS_SECRET_ACCESS_KEY/GITHUB_TOKEN等の秘密も含まれる。SSH 自体は暗号化されるが、送り先は remote daemon のメモリと、そこから spawn される子の環境。felis window retarget --host remote -- <cmd>/felis ssh remote -- <cmd>で新規 remote session を作るとき、dial する window のローカル環境が remote daemon に送られる。ローカルの秘密が remote host に漏洩し得る。SpawnArgs.env(明示的--env KEY=VAL)はSpawnArgs.env_baseの上に overlay されるが、env_base自体のフィルタリングはfelis-ptyの denylist のみ。allowlist はない。問い(1.0 でしか変えられない)
env_base/FRLYの「全環境を送る」設計をこのまま凍結するか? 最小限の allowlist に絞るか?破壊的変更案
env_base/FRLYを allowlist に絞る。PATH/HOME/SHELL/TERM/LANG/LC_*/SSH_AUTH_SOCKのみを送り、他は送らない。SpawnArgs.env_baseの cap(4096/1MiB)はそのままに、送るキー集合を固定。docs/reference/ipc.md"Session (kind = 4)" の env_base 記述を allowlist として normative に。--env以外は送らない。fill_for_carrier/capture_environmentをやめ、env_baseは常にNone。remote spawn は常に remote daemon の環境 + 明示的--envのみ。1.0 で最も安全だが、既存の「ローカルのPATHを引き継ぐ」挙動が失われる。capture()がAWS_*/*_TOKEN/*_SECRETを含むときにtracing::warn(値は出さずキー名のみ)し、docs/reference/ipc.mdに「ローカル秘密が remote に送られる」旨を Security Considerations として追記。判定基準
explanation/security-model.md"Process and environment boundary" とreference/ipc.mdの env_base / FRLY 記述が、実装のenv_base::capture/relay::capture_environmentと一致していること。felis --host remote -- envで子のenvにローカルのAWS_SECRET_ACCESS_KEYが現れないこと(allowlist or no-send)。felis sessions spawn --env FOO=barの明示的 overlay は常に最優先で残ること(REQ-912)。対象ファイル
crates/felis-client-core/src/env_base.rs,crates/felis-daemon/src/relay.rs(capture_environment),crates/felis-protocol/src/messages/session.rs(SpawnArgs),crates/felis-protocol/proto/felis.proto(EnvBase),crates/felis-transport/src/preface.rs(CarrierBlock),docs/reference/ipc.md,docs/explanation/security-model.md,docs/explanation/architecture/session-lifecycle.mdcc @natsukium
Closed because the reported cross-host secret leak is not present.
felis-client-core::env_base::fill_for_carriersetsSpawnArgs.env_baseonly forCarrier::Local; the SSH case sendsNone. TheFRLYblock is created byfelis-daemon relayafter SSH starts the remote command, sorelay::capture_environment()captures the remote login environment, not the local window environment. This invariant is also recorded indocs/explanation/security-model.mdunder “Process and environment boundary” and covered byonly_a_local_carrier_carries_an_environment. A local variable reaches the remote only if SSH itself is configured to forward it, which remains SSH policy.