Skip to content

SSH ASKPASS helper used before 1Password is authenticated, causing manual passphrase prompts on every restart #3

Description

@kylebrodeur

Problem Summary

Every time the system restarts or a new shell session starts, the SSH key passphrase must be entered manually before 1Password is unlocked. Once 1Password is unlocked, the passphrase resolution works as expected, but the initial bootstrap sequence is broken.

Root Cause Analysis

1. setup_ssh_agent.sh does not verify op authentication before configuring SSH_ASKPASS

In src/setup_ssh_agent.sh:

if command -v op >/dev/null 2>&1 && [[ -f "$_askpass_helper" ]] && [[ -x "$_askpass_helper" ]]; then
  if ! grep -q "REPLACE/WITH/YOUR" "$_askpass_helper" 2>/dev/null; then
    export SSH_ASKPASS="$_askpass_helper"
    export SSH_ASKPASS_REQUIRE="prefer"
    _askpass_vars_set=true
  fi
fi

The script verifies that:

  • op CLI is installed
  • The askpass helper file exists and is executable
  • The placeholder reference has been replaced

It does NOT verify that op is actually authenticated. On a fresh boot:

  1. The 1Password desktop app is locked
  2. There is no cached session token yet (or it has expired)
  3. op vault list would fail with "not currently signed in"
  4. Yet SSH_ASKPASS is still set to the 1Password helper

2. askpass-1password.sh fails silently when op is not authenticated

In src/askpass-1password.sh:

op read "$OP_SECRET_REFERENCE"

When op is not authenticated, op read fails and writes an error to stderr, but nothing (or an empty string) goes to stdout. ssh-add interprets this empty/failed output as the passphrase, which is incorrect. Because SSH_ASKPASS_REQUIRE=prefer (not force), ssh-add then falls back to a terminal prompt, forcing the user to type the passphrase manually.

3. op-session-manager.sh interactive signin may break in .zshrc

In src/op-session-manager.sh:

op signin > "$TOKEN_FILE"

This redirects stdout to the token file. If op signin outputs prompts to stdout (depending on auth method), the user may not see them in the .zshrc context, causing the signin to hang or fail silently.

4. SSH_ASKPASS and SSH_ASKPASS_REQUIRE are unset after keychain runs

if $_askpass_vars_set; then
  unset SSH_ASKPASS
  unset SSH_ASKPASS_REQUIRE
fi

This means even if a user later authenticates 1Password and wants to run ssh-add manually, the ASKPASS environment is gone and must be manually recreated.

Impact

  • On every system restart / new login, the user sees a manual SSH passphrase prompt
  • The whole value proposition of "1Password provides the passphrase automatically" is lost at the most critical moment
  • The setup documentation explicitly states the session manager must come before SSH setup, but even with correct ordering, the SSH script does not gate on 1Password readiness

Reproduction Steps

  1. Reboot the system (or open a fresh terminal with no existing ssh-agent)
  2. Ensure 1Password desktop app is locked (or no OP_SERVICE_ACCOUNT_TOKEN is exported)
  3. Open a new shell where .zshrc sources ~/.ssh/setup_ssh_agent.sh
  4. Observe that keychain runs and ssh-add prompts for passphrase manually
  5. Only after unlocking 1Password separately does op read work

Environment

  • Linux/WSL/macOS with keychain installed
  • 1Password CLI (op) installed
  • SSH key with passphrase
  • Desktop app integration or session token caching (not service account)

Suggested Fixes

Fix 1: Gate SSH_ASKPASS on 1Password authentication status

In setup_ssh_agent.sh, add an authentication check:

if command -v op >/dev/null 2>&1 && [[ -f "$_askpass_helper" ]] && [[ -x "$_askpass_helper" ]]; then
  if ! grep -q "REPLACE/WITH/YOUR" "$_askpass_helper" 2>/dev/null; then
    # NEW: Only use 1Password ASKPASS if op is actually authenticated
    if op vault list >/dev/null 2>&1; then
      export SSH_ASKPASS="$_askpass_helper"
      export SSH_ASKPASS_REQUIRE="prefer"
      _askpass_vars_set=true
    else
      if [[ -n "$OP_DEBUG" ]]; then
        echo "[DEBUG] 1Password not authenticated. Skipping ASKPASS config." >&2
      fi
    fi
  fi
fi

Fix 2: Add error handling to askpass-1password.sh

# Verify op is authenticated before trying to read
if ! op vault list >/dev/null 2>&1; then
  # Exit non-zero so ssh-add can fall back to terminal prompt
  echo "1Password not authenticated" >&2
  exit 1
fi

op read "$OP_SECRET_REFERENCE"

Fix 3: Consider not unsetting SSH_ASKPASS after keychain

Leaving SSH_ASKPASS in the environment allows manual ssh-add operations to also benefit from 1Password after the user authenticates. Alternatively, export a helper function or alias.

Fix 4: For op-session-manager.sh, ensure interactive prompts are visible

Consider using /dev/tty for op signin output when in an interactive shell, or use op signin --raw with explicit prompting, to avoid stdout redirection swallowing prompts:

op signin > "$TOKEN_FILE" 2>/dev/tty

Files Affected

  • packages/1password-cli-tools/src/setup_ssh_agent.sh
  • packages/1password-cli-tools/src/askpass-1password.sh
  • packages/1password-cli-tools/src/op-session-manager.sh
  • packages/1password-cli-tools/lib/config.js (.zshrc block generation)

Related Documentation

  • SKILL.md - SSH Agent (Troubleshooting section mentions this exact symptom but the docs only suggest checking env vars, not fixing the auth check)
  • docs/SETUP.md (Order of sourcing is documented correctly, but the scripts don't enforce the dependency)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions