diff --git a/plugins/ssh-terminal/src/frontend/terminal/Terminal.tsx b/plugins/ssh-terminal/src/frontend/terminal/Terminal.tsx index da716f7ef..d71b17673 100644 --- a/plugins/ssh-terminal/src/frontend/terminal/Terminal.tsx +++ b/plugins/ssh-terminal/src/frontend/terminal/Terminal.tsx @@ -1262,6 +1262,8 @@ const TerminalInner = forwardRef( } function maybeOfferPasswordFill(strippedData: string) { + if (hostConfig.terminalConfig?.passwordPromptAutoFill === false) return; + // PTY output can split a short prompt like "[sudo] password for user: " // across multiple WebSocket chunks, so match against a rolling buffer // of recent output rather than each chunk in isolation. diff --git a/plugins/ssh-terminal/src/frontend/types.ts b/plugins/ssh-terminal/src/frontend/types.ts index 2d21fddad..2e71507c5 100644 --- a/plugins/ssh-terminal/src/frontend/types.ts +++ b/plugins/ssh-terminal/src/frontend/types.ts @@ -28,6 +28,7 @@ export interface TerminalConfig { startupSnippetId: number | null; autoMosh: boolean; moshCommand: string; + passwordPromptAutoFill?: boolean; sudoPasswordAutoFill: boolean; sudoPassword?: string | null; keepaliveInterval?: number; diff --git a/src/types/index.ts b/src/types/index.ts index d5a4f7bad..68bf1ebc3 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -377,6 +377,7 @@ export interface TerminalConfig { startupSnippetId: number | null; autoMosh: boolean; moshCommand: string; + passwordPromptAutoFill?: boolean; sudoPasswordAutoFill: boolean; sudoPassword?: string | null; keepaliveInterval?: number; diff --git a/src/ui/lib/terminal-themes.ts b/src/ui/lib/terminal-themes.ts index e989eacf7..6a243c2b9 100644 --- a/src/ui/lib/terminal-themes.ts +++ b/src/ui/lib/terminal-themes.ts @@ -856,6 +856,7 @@ export const DEFAULT_TERMINAL_CONFIG = { startupSnippetId: null as number | null, autoMosh: false, moshCommand: "mosh-server new -s -l LANG=en_US.UTF-8", + passwordPromptAutoFill: true, sudoPasswordAutoFill: false, keepaliveInterval: undefined as number | undefined, keepaliveCountMax: undefined as number | undefined, diff --git a/src/ui/locales/en.json b/src/ui/locales/en.json index 5f7483034..a3403963f 100644 --- a/src/ui/locales/en.json +++ b/src/ui/locales/en.json @@ -567,6 +567,8 @@ "linkClickBehaviorDefault": "Default (follow app setting)", "linkClickBehaviorConfirm": "Show popup to open or copy", "linkClickBehaviorDirect": "Open directly", + "passwordPromptAutoFillLabel": "Offer Password Auto-fill", + "passwordPromptAutoFillDesc": "Offer to fill in the saved password when the terminal asks for one. Turn off to never auto-fill any password on this host.", "sudoPasswordAutoFillLabel": "Sudo Password Auto-fill", "sudoPasswordAutoFillShortDesc": "Automatically provide sudo password when prompted", "sudoPasswordAutoFillDesc": "Store a sudo password so host metrics, terminal prompts, and others can run privileged commands automatically.", diff --git a/src/ui/sidebar/HostEditor.tsx b/src/ui/sidebar/HostEditor.tsx index bddaaf2d4..2e833da8c 100644 --- a/src/ui/sidebar/HostEditor.tsx +++ b/src/ui/sidebar/HostEditor.tsx @@ -1005,6 +1005,15 @@ export function HostEditor({ onChange={(v) => setField("allowLegacyAlgorithms", v)} /> + + setField("passwordPromptAutoFill", v)} + /> + { expect(tc?.sudoPasswordAutoFill).toBe(true); expect(tc?.sudoPassword).toBe("sudo-secret"); }); + + it("defaults password prompt autofill on and saves it when turned off", () => { + expect(createHostEditorForm(null).passwordPromptAutoFill).toBe(true); + + const form = { + ...createHostEditorForm(null), + passwordPromptAutoFill: false, + }; + const payload = buildHostEditorPayload(form, sshOnly); + + expect(payload.terminalConfig?.passwordPromptAutoFill).toBe(false); + }); }); describe("sudo password persistence indicator", () => {