Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sudo not working anymore after running any brew command #17915

Closed
3 tasks done
richard-kramer opened this issue Jul 31, 2024 · 10 comments
Closed
3 tasks done

sudo not working anymore after running any brew command #17915

richard-kramer opened this issue Jul 31, 2024 · 10 comments
Labels
bug Reproducible Homebrew/brew bug

Comments

@richard-kramer
Copy link

brew doctor output

Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: Some installed formulae are deprecated or disabled.
You should find replacements for the following formulae:
  [email protected]
  python-packaging

Verification

  • My "brew doctor output" above says Your system is ready to brew. and am still able to reproduce my issue.
  • I ran brew update twice and am still able to reproduce my issue.
  • This issue's title and/or description do not reference a single formula e.g. brew install wget. If they do, open an issue at https://github.com/Homebrew/homebrew-core/issues/new/choose instead.

brew config output

HOMEBREW_VERSION: 4.3.12
ORIGIN: https://github.com/Homebrew/brew
HEAD: 874d2da45344d3b27aa740e555b0210d8c474220
Last commit: 24 hours ago
Core tap JSON: 31 Jul 06:37 UTC
HOMEBREW_PREFIX: /home/linuxbrew/.linuxbrew
HOMEBREW_CASK_OPTS: []
HOMEBREW_DISPLAY: :0
HOMEBREW_EDITOR: code -w
HOMEBREW_MAKE_JOBS: 16
Homebrew Ruby: 3.3.4 => /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/3.3.4/bin/ruby
CPU: 16-core 64-bit zen
Clang: N/A
Git: 2.43.0 => /bin/git
Curl: 8.5.0 => /bin/curl
Kernel: Linux 6.8.0-39-generic x86_64 GNU/Linux
OS: Ubuntu 24.04 LTS (noble)
Host glibc: 2.39
/usr/bin/gcc: 13.2.0
/usr/bin/ruby: N/A
glibc: N/A
gcc@11: N/A
gcc: 14.1.0_2
xorg: N/A

What were you trying to do (and why)?

Running brew commands inside scripts that also contain other commands run with sudo. This is part of my system setup/update process, so I only have to run one command to update everything.

The issue is also reproducible outside any custom script by checking sudo privileges after running any brew command.

What happened (include all command output)?

After running any brew command, previous sudo privileges are lost.

# grant sudo privileges

sudo -l
# =>
# Matching Defaults entries for <user> on <host>:
#     env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty, !tty_tickets, timestamp_timeout=-1
#
# User <user> may run the following commands on <host>:
#     (ALL : ALL) ALL

brew info
# => 193 kegs, 99,489 files, 3.4GB

sudo -l
# => 
# [sudo] password for <user>:
# (asks for password, privileges were revoked)

It seems like the brew info command can be replace with any other brew command. I tried:

  • brew info
  • brew install
  • brew help
  • brew doctor
  • brew config
  • NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

What did you expect to happen?

I expected the already granted sudo privileges to stay and be reusable for following commands.

I strongly suspect #17694 to be the cause of this problem, as it only popped up after I made a recent update to homebrew. Maybe there is another way to revoke sudo permissions for the formula only, without it affecting the parent environment?

Step-by-step reproduction instructions (by running brew commands)

# grant sudo privileges

sudo -l
# =>
# Matching Defaults entries for <user> on <host>:
#     env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty, !tty_tickets, timestamp_timeout=-1
#
# User <user> may run the following commands on <host>:
#     (ALL : ALL) ALL

brew info
# => 193 kegs, 99,489 files, 3.4GB

sudo -l
# => 
# [sudo] password for <user>:
# (asks for password, privileges were revoked)
@richard-kramer richard-kramer added the bug Reproducible Homebrew/brew bug label Jul 31, 2024
@MikeMcQuaid
Copy link
Member

This is intentional, WONTFIX and a duplicate of #17905

@MikeMcQuaid MikeMcQuaid closed this as not planned Won't fix, can't repro, duplicate, stale Jul 31, 2024
@MrCee
Copy link

MrCee commented Aug 12, 2024

Is there a command to prevent this from happening?

@richard-kramer
Copy link
Author

Not really a single command, but I mitigated the issue by adding a custom brew command, which opens its own TTY session:

#!/usr/bin/bash

faketty() {
  script -qefc "$(printf "%q " "$@")" /dev/null
}

faketty "/home/linuxbrew/.linuxbrew/bin/brew" "$@"

Add this file to PATH (e.g. by linking it inside $HOME/.local/bin) and it will replace the brew command, directly referencing the binary.

This only works, if tty_tickets is enabled in the sudoers config file:

# /etc/sudoers

# ...

Defaults        tty_tickets

#...

Alternatively, a file with this content can be placed in /etc/sudoers.d/.

This is definitely more of a dirty workaround, but works for my case.

@gromgit
Copy link
Member

gromgit commented Aug 12, 2024

This only works, if tty_tickets is enabled in the sudoers config file:

Note that:

  1. tty_tickets is deprecated in favor of timestamp_type.
  2. timestamp_type = tty is already the default, so unless it's set to something else, your hack should automatically work for everyone.

And while I use the word "hack", it's really the logical solution to isolate any command that resets sudo credential caching.

@MrCee
Copy link

MrCee commented Aug 14, 2024

Yes! I happened to find a similar way which worked on my system, my system doesn't come with visudo so I'm not keen to touch the /etc/sudoers file but I can simply add administrator access as a file e.g. /etc/sudoers.d/custom_homebrew_sudoers and trap to delete it later.
It's the same principal as above but not dealing with timestamp. Just add a file and delete it later on exit.

#!/bin/zsh
sudo -v || { echo "Failed to cache sudo credentials"; exit 1; }
SUDOERS_FILE="/etc/sudoers.d/custom_homebrew_sudoers"
cat <<EOF | sudo tee $SUDOERS_FILE > /dev/null
Defaults syslog=authpriv
root ALL=(ALL) ALL
%administrators ALL=NOPASSWD: ALL
EOF
sudo chmod 0440 $SUDOERS_FILE
trap 'sudo rm -f $SUDOERS_FILE' EXIT

Would you class this as dirty? Let me know :)

@gromgit
Copy link
Member

gromgit commented Aug 14, 2024

It's the same principal as above

The script hack isolates Homebrew's credential invalidation to the brew ... command, so e.g. if brew install ... invokes sudo for whatever reason, the user has a chance to go "whoa, why is it asking for root privileges? Ctrl-C!!!".

Your hack suppresses all credential checks, so any formula/cask (in fact, any code brew runs as it does its thing) can have silent root access to your system.

It's really not the same principle. At all.

Would you class this as dirty?

Yes.

Potentially catastrophic? Also yes.

@MrCee
Copy link

MrCee commented Aug 14, 2024

It's only really active in that state for 3-4 minutes where sudo just doesn't cache. The trap removes the privilege instantly on Ctrl-C or any other variant. Potentially I could tighten this up. Or scrap this method.

@MrCee
Copy link

MrCee commented Aug 14, 2024

Okay this might be better but would like advice...

#!/bin/zsh
sudo -v || { echo "Failed to cache sudo credentials"; exit 1; }
SUDOERS_FILE="/etc/sudoers.d/custom_homebrew_sudoers"
cleanup() {
    sudo rm -f "$SUDOERS_FILE"
}
trap cleanup EXIT INT TERM HUP QUIT ABRT ALRM PIPE
CURRENT_USER=$(whoami)
cat <<EOF | sudo tee $SUDOERS_FILE > /dev/null
Defaults syslog=authpriv
root ALL=(ALL) ALL
$CURRENT_USER ALL=NOPASSWD: ALL
EOF
sudo chmod 0440 $SUDOERS_FILE

I'm missing what the catastrophic issue is. The installation script only has this access for a very carefully planned install list. It can only run if you have root initially so sudo -v is cached.
Each brew command would normally be installed, the issue is that when brew is finished with it's installation, my script cannot continue because the cached sudo has been cleared.

Okay so it's not the same thing as timestamp. But I've set the trap for exit. And even during the script I'm deleting SUDOERS_FILE="/etc/sudoers.d/custom_homebrew_sudoers" as soon as it is no longer required.

@gromgit
Copy link
Member

gromgit commented Aug 14, 2024

  1. You're running brew under this "anything that wants sudo can get it without a password" regime.
  2. Old brew loads and evaluates all formula files under many circumstances, which can result in launching sudo if a formula is crafted that way, even if you don't directly reference that formula.
  3. Modern brew use the API JSON where possible, which mitigates but doesn't completely prevent [2] from happening (e.g. caveats get executed on brew info).
  4. Homebrew maintainers can only really police the core and cask taps.
  5. sudo runs in Homebrew are usually hidden in upstream build assets and binary cask installers.

The installation script only has this access for a very carefully planned install list.

You've only posted the script preamble, so everyone reading it has to expect the worst: that it's a generic script with no restrictions.

the issue is that when brew is finished with it's installation, my script cannot continue because the cached sudo has been cleared.

Use the script trick and batch all your desired casks into a single brew install, then you only need to type in your password once.

Bottom line: Homebrew maintainers deliberately quashed sudo credential caching in brew for reasons I'm not privy to, but your hack basically opens a different credential backdoor, does it quietly, and disables any further sudo-related security improvements that the Homebrew maintainers may introduce in future. You won't know if sudo was invoked by anything in the brew install formula/cask workflow or any other brew subcommand.

As you might guess, I'd never ever run something like this, but in the end, it's your box, your rules...your consequences.

@Homebrew Homebrew locked as resolved and limited conversation to collaborators Aug 15, 2024
@MikeMcQuaid
Copy link
Member

Homebrew maintainers deliberately quashed sudo credential caching in brew for reasons I'm not privy to

See https://brew.sh/2024/07/30/homebrew-security-audit/ for the now disclosed reasons 😁.

Locking this. Please feel free to continue any discussion in Homebrew/discussions.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Reproducible Homebrew/brew bug
Projects
None yet
Development

No branches or pull requests

4 participants