Support restricted `sudoers` rules
@rgoldberg is already working on this.
Since Aug 12, 2026.
- Dominant language
- Swift
- Stars
- 12.4k
- Forks
- 299
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 1
Description
Problem(s) addressed
request is for a least-privilege boundary for running specific mas install or update operations non-interactively.
The released 7.0 implementation and the privilege implementation currently on main expose different problems for restricted NOPASSWD configurations:
- 7.0 re-executes
masthroughsudowith an internal environment assignment, which requires an additionalsudoersenvironment exception. - Current
mainnow invokes privileged system tools directly. That removes the environment-assignment failure, but an exact rule authorizing the requestedmascommand no longer authorizes the commands thatmaspasses tosudo.
The default interactive behavior can remain unchanged. This request is for a supported interface for automation that deliberately grants only a specific MAS operation, rather than broad passwordless root access.
Observed behavior in 7.0
I use an exact rule shaped like this for a declared application:
<user> ALL=(root) NOPASSWD: <mas-path> update --force 803453959
When an update requires elevation, MAS 7.0 actually executes the equivalent of:
$ sudo MAS_NO_AUTO_INDEX=1 <mas-path> update --force 803453959
sudo therefore rejects the internal environment assignment even though the mas command itself is authorized:
sudo: sorry, you are not allowed to set the following environment variables: MAS_NO_AUTO_INDEX
This comes from the 7.0 elevation implementation:
https://github.com/mas-cli/mas/blob/v7.0.0/Sources/mas/Utilities/Processes/Sudo.swift#L20-L29
A command-specific workaround is possible:
Defaults!<mas-path> env_keep += "MAS_NO_AUTO_INDEX"
However, that makes the external privilege policy depend on an internal mas optimization and does not address the privilege boundary used by current main.
Remaining gap on current main
The privilege-handling changes merged for the 7.1 release (as it currently stands from what I see) no longer re-execute the MAS binary as root.
$ sudo /usr/sbin/installer -dumplog -pkg <dynamic-temporary-path> -target /
$ sudo /bin/sh -c '<copy/chown/chmod receipt script>' -- <dynamic-paths...>
Relevant code:
- https://github.com/mas-cli/mas/blob/1eeacfca0e0ddf9e3a5b9cfe4205aa6b8e2951b7/Sources/mas/Models/AppStoreAction.swift#L290-L340
- https://github.com/mas-cli/mas/pull/1276
Based on that merged code, the exact NOPASSWD rule for
<mas-path> update --force 803453959 cannot match these child sudo commands.
A policy would instead need to authorize installer with dynamic package paths and a root shell command with dynamic receipt paths. Such rules are broader, more brittle across MAS releases, and no longer express the intended policy:
"allow MAS to update this app ID."
This also leaves the restricted rule suggested in the discussion of #1095 without an equivalent supported shape for the new privilege model:
https://github.com/mas-cli/mas/issues/1095#issuecomment-3592153547
Motivation
This matters for brew bundle, declarative workstation configuration, and other unattended update workflows. Homebrew itself cannot safely be run as root, while granting broad passwordless access to generic system tools defeats the purpose of using an app-specific sudoers rule.
Proposed solution(s)
a supported way to authorize a specific MAS operation and app ID without requiring any of the following:
SETENVor a global environment exception;- broad passwordless access to
/usr/sbin/installer; - passwordless access to
/bin/shwith dynamic arguments; - running Homebrew or the entire caller as root; or
- policies coupled to MAS temporary paths and internal subprocesses.
For example, MAS could expose a root-owned privileged helper whose stable command line contains the requested operation and app IDs. The helper could validate and manage installer packages and receipts internally. A restricted policy could then remain shaped like:
<user> ALL=(root) NOPASSWD: <mas-helper-path> update 803453959
Related
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.