#1511

Safe user-input handoff for sudo/password prompts in interactive shell sessions

Openkvnlooopened 15d ago

Problem

When an agent-run command needs a sudo password or other sensitive terminal input, there is no documented private user-input handoff. The agent can use shell with tty: true and send interact.chars, but credentials must not pass through chat or model-generated tool arguments.

In the observed workflow, sudo -n true exited 1 with sudo: a password is required. The workaround was opening a separate Tern terminal pane for the user. That is terminal-specific and not an fx-native handoff.

Installed fx version: 0.0.15, Linux (CachyOS).

This is a feature/discoverability request, not a confirmed credential-leak vulnerability. If a private attachment flow already exists, documenting it and exposing its availability to the agent may address part of the problem. Searches for sudo, password, and interactive terminal did not identify an obvious duplicate.

Proposed UX

  1. An interactive shell command waits for user input.
  2. fx offers an explicit local action such as “Open private terminal”, showing the command and session identity.
  3. The user explicitly attaches and types directly into the existing PTY, not the chat composer.
  4. The user explicitly returns control to the agent.

Preserve the same PTY and foreground process, rather than spawning another terminal. Enter should submit to the child, not automatically leave private mode. A model may request human attention with session metadata only; it must not receive credentials or human authority proofs.

Implementation triage

Source inspection was against upstream main at d72b46594ca69b108b159e4e02a8e5ec4d3d76b3, not necessarily the installed binary. These are proposed integration points, not a tested patch.

Recommended surface: UI-owned private takeover of an existing PTY, reusing terminal authority and write leases. Avoid a new model-facing password field or routing credentials through shell.interact.

Existing foundations:

No distinct production UI caller of the human-takeover authority constructor was found in the inspected paths/exact-symbol search. This is a bounded finding, not proof no alternative attachment path exists; a pinned whole-source caller audit should precede implementation.

Suggested changes:

  • Add explicit local attachment state and input ownership in the UI/event-loop ingress, before composer decoding, history, or input recording.
  • Acquire existing human authority and the human write lease before accepting private bytes; coordinate with in-flight agent writes rather than bypassing authorization.
  • Use a UI-only internal PTY write path, auditing temporary buffers, copies, diagnostics, and cancellation. Do not put private bytes in model tool arguments or permission review payloads.
  • Handle detach, child exit, EOF, resize, acquisition failure, owner loss, and cleanup explicitly.
  • Keep generic terminal execution separate from UI keyboard orchestration.

Confidentiality boundaries

A human write lease is not itself a privacy guarantee:

  • event_loop.zig records stdin before dispatch. Private input must bypass recording at ingress, including when FX_RECORD_INPUT is enabled.
  • The existing takeover test permits agent reads, screen access, and signals during takeover.
  • Session.appendOutput journals output before emulator/checkpoint processing; the managed observer subsequently constructs replay/projected output.

Normal sudo disables echo, but a general private-input promise cannot rely on the child doing so. Private takeover should suppress durable and model-visible output capture at the backend, render locally using ephemeral state, and prevent private screen contents from leaking through later checkpoints or replay. Merely pausing the observer is insufficient. Omitted output should be represented explicitly.

Document the scope: fx can protect its own input/output capture paths, not logs maintained by the child or external terminal recording.

Acceptance tests

  • A fake password sentinel reaches an echo-disabled child on the same PTY.
  • The sentinel is absent from model/tool arguments, permission reviews, chat/history, input/display recordings, journals, checkpoints, replay, and model-visible results, including with input recording enabled.
  • An echo-enabled child verifies that private output is also excluded.
  • Competing agent/human writes, concurrent observers, stale authority, and owner loss are handled safely.
  • Split input, paste, UTF-8, detach mid-buffer, and deferred input never replay into the chat composer.
  • Child exit, cancellation, EOF, resize, and failed acquisition/release restore a usable UI without accidentally granting agent input ownership.

Verification

Triage used public source inspection and installed version/CLI checks only. No implementation changes, builds, or behavioral tests were performed. The requested architecture and privacy guarantees need runtime verification before being presented as supported behavior.

Activity

0

No activity yet.