fix: resolve "terminal is required" error when uninstalling Homebrew casks that run embedded sudo installers#1004
Conversation
|
@manuelguido Thank you for the clear write-up. Your root-cause analysis (the Perl fallback detaching the TTY) is exactly right. I fixed #1003 on main from the other direction: the timeout fallback now keeps the controlling terminal ( I really appreciate the contribution and the tests; your TTY analysis directly informed the fix. Thank you! |
|
@tw93 Perfect! Way cleaner than my approach. Keeping the TTY directly makes much more sense. Thank you for this great project! I stopped using other tools to clean my mac since I found this one 🔥 |
Problem
Uninstalling certain Homebrew casks (e.g. Wireshark) fails with:
sudo: a terminal is required to read the password
sudo: a password is required
Error: Failure while executing; /usr/bin/sudo … /usr/sbin/installer … exited with 1.
Homebrew cask uninstall scripts can call
sudodirectly for embedded.pkginstallers. Mole runsbrew uninstallthrough a timeout wrapperwhose Perl fallback (
run_with_timeout) detaches the controllingterminal, so the inner
sudohas no TTY and cannot prompt for a password.Fix
lib/core/sudo.sh—create_sudo_askpass_helper()Adds a new helper that writes a minimal temp script (
mktemp, mode 700)which shows a native macOS GUI password dialog via
osascript. Thepassword is never written to disk;
sudoonly invokes the helper when itactually needs one (a still-valid timestamp skips the prompt entirely).
The function is a no-op in test mode and on non-macOS systems.
lib/uninstall/brew.sh—brew_uninstall_cask()Before calling
brew uninstall, exportsSUDO_ASKPASSto the helperpath. Homebrew automatically appends
sudo -AwhenSUDO_ASKPASSisset, so any nested
sudoinside a cask script can obtain the passwordthrough the GUI without needing a TTY.
In the
sudo -u "$SUDO_USER" env …branch the variable is re-injectedexplicitly via the inner
envlist (the outersudostrips theenvironment). Cleanup (temp file removal +
SUDO_ASKPASSrestore) isdone inline after
brewexits — not via aRETURNtrap, which in bash3.2 is not function-scoped and would re-fire on the caller's return with
locals out of scope, aborting under
set -u.tests/brew_uninstall.batsTwo new tests:
brew_uninstall_cask exports SUDO_ASKPASS so inner sudo prompts work— verifies the variable is visible tobrewduring uninstall.brew_uninstall_cask restores a pre-existing SUDO_ASKPASS value— verifies the prior value is restored after the call.Resolves #1003