Skip to content

v0.15.0 - Safer SSH Password Automation (2026-07-06)

What Changed?

This release hardens the pexpect-based SSH password automation in gear.py (tracked as #51): commands are now passed as argv lists instead of a shell-joined string, first-time SSH connections no longer hang or blindly trust an unknown host key, and both the password-prompt and transfer-wait timeouts are configurable and independent of each other.


What's New

Main Feature: Hardened SSH Password Automation

What it does: run_rsync()'s password-automation path (gear._run_rsync_with_password) now:

  • Spawns rsync with an argv list (pexpect.spawn(cmd[0], args=cmd[1:])) instead of a " ".join(cmd) string, so source/target paths or options containing spaces or shell metacharacters are no longer re-parsed (and potentially broken) by a shell.
  • Detects the SSH host key confirmation prompt (Are you sure you want to continue connecting (yes/no)?) that appears on a host's first connection. Previously this wasn't in the expect() pattern list at all, so fnb would just hang until TIMEOUT. Now it logs guidance to verify and register the host key manually (ssh-keyscan or a manual ssh login) and aborts — fnb never auto-confirms an unknown host key.
  • Reads the password-prompt timeout from a new FNB_TIMEOUT environment variable (env.get_timeout()), instead of a hardcoded 30 seconds.
  • Uses a separate transfer_timeout (default: unlimited) for the post-password EOF wait, so a large transfer on a slow link isn't cut off by the same short timeout meant only for detecting the password prompt.

The expect() branches also moved from matching on a positional index (i == 0/1/2) to matching on a name paired with each pattern, so adding or reordering patterns can't silently shift an unrelated branch.

How to use it: No new flags. Set FNB_TIMEOUT in .env (or the environment) to change how long fnb waits for the SSH password prompt:

# .env
FNB_TIMEOUT=60

If fnb reports a host key verification prompt, connect once manually to accept the key, then retry:

ssh user@example.com          # accept the host key interactively
# or
ssh-keyscan -H example.com >> ~/.ssh/known_hosts
fnb fetch logs

Installation

Quick Start

# Get the release
git checkout v0.15.0

# Setup
uv sync --all-groups

# Run CLI
uv run fnb --help

What's Different from the Last Version?

✅ Added

  • env.get_timeout() reads FNB_TIMEOUT (falling back to 30s if unset or invalid)
  • run_rsync()/_run_rsync_with_password() gained a transfer_timeout parameter, decoupling the transfer-wait timeout from the password-prompt timeout
  • env.sample documents the new FNB_TIMEOUT variable

🔧 Changed

  • _run_rsync_with_password() now takes the rsync command as a list (cmd: list[str]) rather than a pre-joined string
  • expect() branch matching uses named patterns instead of positional indices

🐛 Fixed

  • pexpect.spawn() no longer breaks on source/target paths or options containing spaces or shell metacharacters
  • SSH host key confirmation prompts on first-time connections no longer hang until TIMEOUT — fnb now detects them, logs guidance, and aborts instead of blindly trusting an unverified host
  • A slow/large transfer is no longer at risk of being cut off by the short password-prompt timeout

Is It Safe to Upgrade?

Backward Compatible: Yes.

  • Configuration file format (fnb.toml) and CLI arguments are unchanged
  • FNB_TIMEOUT is optional; if unset, behavior matches the previous hardcoded 30-second default
  • If you were relying on fnb auto-confirming a host's first SSH connection (it never explicitly did, but would otherwise hang until TIMEOUT), you'll now see a clear message asking you to verify the host key manually instead of a timeout

Tests Passed

  • ✅ 132 unit and integration tests passed
  • ✅ 89% code coverage
  • ✅ All pre-commit hooks pass (mypy, ruff, trailing whitespace, etc.)

Release Details

  • Date: 2026-07-06
  • Version: v0.15.0
  • Commits: 4 commits since v0.14.0, all closing out issue #51
  • 370e781: fix(gear): pass rsync command as argv list to pexpect.spawn
  • 7e0d4c2: fix(gear): handle SSH host key verification prompt without auto-confirming
  • 0f94142: feat(env): make SSH password-prompt timeout configurable via FNB_TIMEOUT
  • d0a6c3b: fix(gear): decouple transfer wait timeout from password-prompt timeout

Next Steps

  • Continue working through remaining review issues from the 2026-07 codebase review (issue #52 is complete; see the review issue tracker for what's left)