diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb index 3d813476c16ca..50efd133e8526 100644 --- a/Library/Homebrew/manpages/brew.1.md.erb +++ b/Library/Homebrew/manpages/brew.1.md.erb @@ -181,6 +181,12 @@ prefix-specific files take precedence over system-wide files (unless Note that these files do not support shell variable expansion (e.g. `$HOME`) or command execution (e.g. `$(cat file)`). +For MDM configuration, package restrictions and policy ownership, see: + +[Homebrew for Mac Admins](https://docs.brew.sh/Homebrew-for-Mac-Admins) + +[Homebrew Package Policies](https://docs.brew.sh/Homebrew-Package-Policies) + <%= environment_variables %> ## USING HOMEBREW BEHIND A PROXY @@ -204,6 +210,8 @@ Homebrew Documentation: Homebrew API: +[Homebrew for teams at work](https://docs.brew.sh/Homebrew-for-Teams) + `git`(1), `git-log`(1) ## AUTHORS diff --git a/docs/Advisory-Matching.md b/docs/Advisory-Matching.md index ee5a50eaa41f1..893a1668e5455 100644 --- a/docs/Advisory-Matching.md +++ b/docs/Advisory-Matching.md @@ -1,5 +1,5 @@ --- -last_review_date: "2026-10-09" +last_review_date: "2026-10-25" --- # Advisory Matching @@ -8,6 +8,8 @@ last_review_date: "2026-10-09" It is an authoring tool, not the installed-package scanner provided by `brew vulns`. Candidates still need [human review](https://github.com/Homebrew/advisory-database/blob/HEAD/CONTRIBUTING.md#reviewing-matched-candidates) before publication. +For operational scanning and remediation, see [Homebrew vulnerability management](Homebrew-Vulnerability-Management.md). + ## Range accuracy and coverage With history enabled, a candidate with a comparable current state and no reviewed range must have its complete affected intervals established from formula history on the latest supported macOS and Linux for both ARM and Intel. diff --git a/docs/Bottles.md b/docs/Bottles.md index becd5a3aa3397..2285a5a75e432 100644 --- a/docs/Bottles.md +++ b/docs/Bottles.md @@ -1,11 +1,14 @@ --- -last_review_date: "2026-07-18" +last_review_date: "2026-10-25" --- # Bottles (Binary Packages) Bottles are produced by installing a formula with `brew install --build-bottle ` and then bottling it with `brew bottle `. This generates a bottle file in the current directory and outputs the bottle DSL for insertion into the formula file. +For private bottle distribution across a team, see [internal software delivery](Homebrew-Fleet-Management.md#publish-internal-tools-through-private-taps) and [download mirror policy](Homebrew-Package-Policies.md#use-mirrors-without-weakening-verification). +For installed build evidence, see [SBOM discovery and collection](Homebrew-Inventory-and-SBOM.md#collect-formula-software-bills-of-materials). + ## Usage When the formula being installed defines a bottle matching your system, it will be downloaded and installed automatically when you run `brew install `. diff --git a/docs/Brew-Bundle-and-Brewfile.md b/docs/Brew-Bundle-and-Brewfile.md index e724964951c21..0f5232cd352d0 100644 --- a/docs/Brew-Bundle-and-Brewfile.md +++ b/docs/Brew-Bundle-and-Brewfile.md @@ -1,5 +1,6 @@ --- -last_review_date: "2026-07-18" +description: Use Homebrew Bundle and Brewfiles to install project dependencies, check software requirements and manage packages on macOS and Linux. +last_review_date: "2026-10-25" --- # Homebrew Bundle, `brew bundle` and `Brewfile` @@ -118,6 +119,11 @@ Homebrew is installed by default on GitHub-hosted macOS runners and can be insta See [GitHub's "Scripts To Rule Them All" `script/bootstrap` example](https://github.com/github/scripts-to-rule-them-all/blob/HEAD/script/bootstrap) for how you might use a `Brewfile` and `brew bundle` to install project dependencies with Homebrew. +### Homebrew for teams at work + +For a shared Brewfile maintained in Git, follow [Homebrew for Teams](Homebrew-for-Teams.md). +The guide covers onboarding colleagues, reviewing changes, coordinating updates and keeping personal tools alongside the team's baseline without an MDM. + ### `brew bundle dump` `Brewfile`s can also be used as a way of saving all supported packages into a single file. `brew bundle dump` is Homebrew's installed-state snapshot command: it records supported installed formulae, casks, taps and other package types as a `Brewfile`. diff --git a/docs/Homebrew-Fleet-Management.md b/docs/Homebrew-Fleet-Management.md new file mode 100644 index 0000000000000..57d6dc782d74b --- /dev/null +++ b/docs/Homebrew-Fleet-Management.md @@ -0,0 +1,198 @@ +--- +description: Manage Homebrew from Jamf Pro, Iru (formerly Kandji), Microsoft Intune and other MDM dashboards. Deploy Brewfiles, report inventory and schedule package updates. +last_review_date: "2026-10-25" +--- + +# Homebrew Fleet Management with MDM and Brewfiles + +You can manage Homebrew across a Mac fleet using an MDM that deploys packages and executes scripts. +Homebrew handles software installation and updates; the MDM handles device enrolment, group membership, scheduling and job results. + +- Table of Contents +{:toc} + +## Integrate with your management system + +Each provider guide takes you through provisioning, deployment, reporting, updates and administrator access: + +- [Jamf Pro](Homebrew-and-Jamf-Pro.md) +- [Iru (formerly Kandji)](Homebrew-and-Iru.md) +- [Microsoft Intune](Homebrew-and-Microsoft-Intune.md) +- [Other management systems](#other-management-systems) + +Start with a pilot device group and collect command output, exit status and inventory before expanding deployment. +These workflows use the MDM's existing agent or script runner; Apple MDM enrolment alone does not provide arbitrary shell execution. +Check your provider's plan, agent requirements, execution timeouts and output limits. + +| Task in your MDM dashboard | Homebrew operation | What to retain or display | +| ------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------- | +| Inspect a device's software | `brew info --json=v2 --installed` | Installed versions, sources and collection time | +| Find devices needing updates | `brew outdated --json=v2` | Package details and a searchable summary field | +| Check the assigned baseline | `brew bundle check --no-upgrade --file=…` | Pass, needs attention or collection failure | +| Install approved software | `brew bundle install --no-upgrade --file=…` or a fixed `brew install` | Assigned group, reviewed arguments and job result | +| Review and apply security fixes | `brew vulns --json` and `brew upgrade --vulnerable` | Findings, scan coverage and a fresh scan afterwards | +| Apply package restrictions | Distribute `/etc/homebrew/brew.env` | Configuration revision and deployment result | + +Use [inventory fields](#reporting-and-administrator-access) for filtering and retain full JSON separately when job logs would truncate it. +An arbitrary JSON export does not automatically become an MDM's built-in software or vulnerability dashboard. +Use the shared deployment and maintenance jobs below after configuring your provider. + +For Linux, follow [Homebrew on Linux](Homebrew-on-Linux.md) and run jobs as the prefix owner through your configuration-management tool. + +### Other management systems + +Use the same jobs with any management system that can deliver packages and run scripts as root: + +1. Complete [account and installer provisioning](Homebrew-for-Mac-Admins.md#initial-provisioning), [central configuration](Homebrew-Package-Policies.md#set-central-configuration-with-brewenv) and [Brewfile deployment](#install-default-software-for-each-team). +2. Assign the baseline and maintenance scripts to a pilot device group, using `as-brew-user` for Homebrew commands. +3. Store short results in custom inventory fields and retain full reports separately. + Keep failed collection and offline devices visible. +4. Schedule approved updates and refresh inventory afterwards. + Check execution timeouts, retries, log retention and whether recurring jobs report every result. +5. Where supported, publish fixed installation actions through self-service and restrict who can edit or run them using the provider's roles. + +Consult your provider's documentation for its script runner, inventory fields and reporting limits. + +## Install default software for each team + +1. [Install Git through Apple's Command Line Tools](Homebrew-for-Mac-Admins.md#install-git-for-management-jobs) before assigning this job; its first Homebrew command is `brew update`, which requires Git. +2. Prepare and review a [shared Brewfile in Git](Homebrew-for-Teams.md). +3. Deliver it to `/Library/Management/Homebrew/Brewfile` through your management system. + Make the file readable by the managing account and writable only by administrators, including its parent directories. +4. Run the installation job below, then retain its check result before assigning more devices. + +The job uses [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) to execute Homebrew as the prefix owner from a root management job: + +```bash +#!/bin/bash +set -euo pipefail + +test -x /opt/homebrew/bin/brew +test -r /Library/Management/Homebrew/Brewfile +/opt/homebrew/bin/brew as-brew-user update +/opt/homebrew/bin/brew as-brew-user bundle install \ + --no-upgrade --file=/Library/Management/Homebrew/Brewfile +/opt/homebrew/bin/brew as-brew-user bundle check \ + --no-upgrade --file=/Library/Management/Homebrew/Brewfile +``` + +`--no-upgrade` separates initial installation from scheduled updates; see the [shared Brewfile workflow](Homebrew-for-Teams.md) for version behaviour, review and cleanup when several teams share a device. + +## Provide self-service software and approvals + +1. Review a requested package and its source using the following commands. + [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) selects the managing account, including from a root job: + +```sh +/opt/homebrew/bin/brew as-brew-user search shellcheck +/opt/homebrew/bin/brew as-brew-user info shellcheck +``` + +2. Publish a fixed action in your MDM's self-service catalogue. + [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) runs the approved installation as the prefix owner: + +```sh +/opt/homebrew/bin/brew as-brew-user install --yes shellcheck +``` + +The MDM authorises the action and runs it as root; `as-brew-user` switches to the prefix owner. +It does not grant standard users the ability to impersonate that account. +Use reviewed package arguments rather than passing arbitrary user input to a privileged script. + +3. Test the action on a pilot device and refresh its inventory. +4. Handle new software requests through your help desk or a Brewfile pull request, then update the device group's policy and catalogue. + +See [package policies](Homebrew-Package-Policies.md) for the distinction between an approved baseline and an enforced allowlist. + +## Schedule updates and staged rollouts + +`brew update` refreshes Homebrew and package metadata. +`brew upgrade` updates installed packages. +Homebrew's automatic metadata refresh does not schedule unattended package upgrades. + +1. Preview the intended upgrade and review services, pins and exceptions. +2. Assign this job to a pilot group. + [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) switches the root job to the prefix owner for each operation: + +```bash +#!/bin/bash +set -euo pipefail + +/opt/homebrew/bin/brew as-brew-user update +/opt/homebrew/bin/brew as-brew-user upgrade --yes --formula +/opt/homebrew/bin/brew as-brew-user info --json=v2 --installed +``` + +3. Review the new inventory and application checks before assigning the wider group. +4. Retain failures and retry offline devices at their next check-in. + +Assign one job at a time to each prefix. +Use separate pilot and general deployment groups; available versions can change between runs because Homebrew is a rolling-release package manager. + +For a preview, run `/opt/homebrew/bin/brew as-brew-user upgrade --dry-run --formula`. +Use `/opt/homebrew/bin/brew as-brew-user upgrade --vulnerable --severity=high --dry-run` to preview updates for formulae with high or critical findings. +For an approved version threshold, use `--minimum-version`; see [vulnerability selection and remediation](Homebrew-Vulnerability-Management.md#select-vulnerable-upgrade-candidates). +Pins, services and packages without an available fix need explicit exception handling. + +Without MDM, schedule the same commands as the owner using launchd on macOS or systemd timers or cron on Linux. + +## Manage applications and services separately + +Follow the [Mac application and service guidance](Homebrew-for-Mac-Admins.md#casks-services-and-shared-destinations) for privileged installers, self-updating applications, service accounts and unattended execution. +Choose one update mechanism per application and schedule closures or restarts with the people affected; avoid routine `--zap` removals because they can remove user data. + +## Publish internal tools through private taps + +1. Create a repository following [How to Create and Maintain a Tap](How-to-Create-and-Maintain-a-Tap.md), with formulae in `Formula/` and casks in `Casks/`. + +Use reviewed pull requests, checksummed releases and [bottle builds](Bottles.md) for the platforms you support. +Your organisation maintains the internal packages and their hosting. + +2. Provision read access for the managing account, then replace the example repository and package names below. + [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) selects that account and its credentials: + +```sh +/opt/homebrew/bin/brew as-brew-user tap example/tools git@github.com:example/homebrew-tools.git +/opt/homebrew/bin/brew as-brew-user trust --formula example/tools/internal-cli +/opt/homebrew/bin/brew as-brew-user install --yes example/tools/internal-cli +``` + +Git credentials must be available to the selected account; another user's SSH agent or login keychain may be unavailable during unattended execution. +Repository authentication and access to private release downloads are separate requirements. +See the [private Git download guidance](FAQ.md#how-do-i-authenticate-private-git-source-downloads). + +Use a credential helper or managed SSH credentials; `brew.env`, Brewfiles and command URLs are not secret stores. +Provision read-only credentials for the managing account through your existing credential-management system, including host verification for SSH. +`as-brew-user` starts with a clean environment, so do not assume a token exported by the root job reaches Homebrew. +Keep tokens out of script output and disable shell tracing around secret retrieval; credentials used on a device are accessible to the account that uses them and to root. + +3. Test repository access and artefact downloads separately. + [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) reproduces the account used by unattended jobs: + +```sh +/opt/homebrew/bin/brew as-brew-user update +/opt/homebrew/bin/brew as-brew-user fetch --formula example/tools/internal-cli +``` + +A token that authenticates Git or the GitHub API does not automatically authenticate arbitrary release URLs. +The formula or cask's download method must support the host's authentication requirements. +Prefer a supported download method or an [internal mirror](Homebrew-Package-Policies.md#use-mirrors-without-weakening-verification) with suitable authentication over a custom download strategy tied to Homebrew internals. +When retiring a tap, remove it from the deployed Brewfile and review its installed packages before running `brew untap`; removing a tap does not uninstall its packages. + +## Reporting and administrator access + +1. Collect [inventory and audit evidence](Homebrew-Inventory-and-SBOM.md) through your MDM. + Run linked collection examples with the absolute `brew` path and [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) from root jobs. + Store short summaries in custom fields and full JSON or SBOMs through your existing collector. + Keep failed collection, incomplete scans and stale devices separate from successful zero-result checks, recording the last successful collection time. + Use reporting tools for fleet searches, exports and notifications, keeping notification credentials on the reporting service. + +2. Use MDM and Git roles and single sign-on to control who can approve changes, deploy jobs and view reports. + +Separate permission to view inventory, run approved jobs and edit scripts or their scope. +An MDM administrator who can edit a root script can execute arbitrary code; Homebrew package restrictions do not reduce that authority. + +3. For managed service providers, use the MDM's customer tenants or supported administrative boundaries and keep each customer's credentials, configuration and reports separate. + +A device group or a saved dashboard filter is not by itself an access-control boundary. +Test a restricted operator account against another customer's devices and reports before granting access. diff --git a/docs/Homebrew-Inventory-and-SBOM.md b/docs/Homebrew-Inventory-and-SBOM.md new file mode 100644 index 0000000000000..38863139cfd5d --- /dev/null +++ b/docs/Homebrew-Inventory-and-SBOM.md @@ -0,0 +1,172 @@ +--- +description: Export Homebrew package inventory as JSON or CSV, collect formula SBOMs and build fleet reports with your existing device-management tools. +last_review_date: "2026-10-25" +--- + +# Homebrew Software Inventory, SBOMs and Audit Reporting + +Homebrew can report installed formulae and casks, package versions, dependencies and formula licence metadata. +Collect that information through your management system to answer which devices have a package, which need an update and which have stopped reporting. +Homebrew also records software bills of materials (SBOMs) for formula installations where available. +These are package records, not a complete device SBOM. + +Run these commands as the Homebrew owner on macOS or Linux, with `brew` and any required tools on `PATH`. +For root management jobs, use the absolute path with [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner), for example `/opt/homebrew/bin/brew as-brew-user` in place of `brew` on Apple Silicon. + +- Table of Contents +{:toc} + +## Export installed software as JSON + +1. Install [Homebrew](Installation.md) and assign a collection job to one pilot device. +2. Create a private report directory and collect the files below. + + ```bash + #!/bin/bash + set -euo pipefail + umask 077 + cd "$(/usr/bin/mktemp -d /var/tmp/homebrew-report.XXXXXX)" + pwd + /bin/date -u '+%Y-%m-%dT%H:%M:%SZ' > collected-at.txt + brew info --json=v2 --installed \ + > homebrew-inventory.json 2> homebrew-inventory.stderr + brew outdated --json=v2 \ + > homebrew-outdated.json 2> homebrew-outdated.stderr + brew config > homebrew-config.txt 2> homebrew-config.stderr + ``` + +3. Retain the directory printed by the job, its exit status and diagnostics even if collection fails. + Import only valid JSON from successful commands; a failed command is not an empty inventory. + The remaining file-processing examples run from that report directory. +4. Upload the snapshot through your existing collector with device identity, Homebrew prefix and collection time. + Remove the local copy after confirmed collection according to your retention policy. + +The inventory object contains `formulae` and `casks` arrays. +For formulae, read installed versions from each formula's `installed` array, not `versions.stable`, which describes the currently available release. +Several kegs of the same formula can remain installed. +The `linked_keg` and installed runtime dependency records help distinguish the active installation from retained versions. +For casks, `installed` records the Homebrew-installed version; it does not necessarily reflect an application that has updated itself. +See [Querying `brew`](Querying-Brew.md) for the JSON interface and its compatibility policy. + +Store snapshots by device identifier, Homebrew prefix and collection time, with the Homebrew version and job result. +One prefix's inventory does not include other installations on the same device. + +## Export a spreadsheet inventory + +1. Include `jq` in your [team Brewfile](Homebrew-for-Teams.md). +2. Convert the captured JSON from the report directory: + +```sh +jq -r ' + ["type", "name", "installed_version", "tap", "licence"], + (.formulae[] | . as $formula | .installed[] | + ["formula", $formula.full_name, .version, + $formula.tap, ($formula.license // "unknown")]), + (.casks[] | + ["cask", .full_token, .installed, .tap, "not reported"]) + | @csv +' homebrew-inventory.json > homebrew-inventory.csv +``` + +3. Import the CSV with spreadsheet formula interpretation disabled; CSV quoting alone does not prevent formula execution. + +This emits one row for each installed formula keg and each cask record. +Keep the original JSON alongside the CSV so dependency and provenance information remains available. +Formula licence metadata describes the formula's declared licence; it is not a complete legal assessment of every bundled component. +Cask metadata does not provide an equivalent licence inventory. + +## Inspect dependencies and installation intent + +1. Select a package from the installed inventory. +2. Inspect its dependencies and users. + +```sh +brew deps --tree git +brew uses --installed git +brew leaves +``` + +`brew deps` describes dependencies from current package definitions. +Use each installed formula entry's `runtime_dependencies` when you need the dependencies recorded for that installation. +`installed_on_request` distinguishes an explicitly requested formula from one brought in as a dependency. +`brew leaves` lists formulae that are not dependencies of other installed formulae; it is not a list of all user-requested software. + +## Collect formula software bills of materials + +Homebrew stores available SPDX JSON SBOMs as `sbom.spdx.json` inside formula kegs. + +1. Start with the [captured inventory](#export-installed-software-as-json). +2. Write a manifest of installed formulae, versions and SBOM paths: + +```sh +jq -r '.formulae[] | .full_name as $name | .installed[] | + [$name, .version, (.sbom // "missing")] | @tsv' homebrew-inventory.json > homebrew-sboms.tsv +``` + +Each formula's `installed` entries include `sbom`: the absolute path of that keg's SPDX file, or `null` when the file is missing. +This includes retained kegs and does not substitute a document from another installed version. +Cask entries do not provide this field. +An absent field from an older Homebrew version means that path discovery is unavailable, not that the document is necessarily missing. + +3. List available documents and archive them with the manifest and inventory. + Run this while the installation is unchanged; if a file disappears during collection, repeat the snapshot: + +```sh +jq -r '.formulae[].installed[] | .sbom // empty' \ + homebrew-inventory.json > homebrew-sbom-paths.txt +/usr/bin/tar -czf homebrew-sboms.tar.gz -T homebrew-sbom-paths.txt +``` + +4. Upload the archive, manifest and inventory together, associated with device, prefix, keg version and collection time. + When the path list is empty, record missing coverage rather than treating an empty archive as a complete SBOM. +Missing documents are missing evidence; the current formula definition cannot replace the installed version's SBOM. +The SPDX records can include source, dependency, patch and build information, but do not provide a complete device SBOM or guarantee that every embedded component is identified. + +## Use software bills of materials for security and software review + +1. Import the SPDX documents into your existing SBOM or software-composition analysis system, preserving the installed-version and device mapping. + Validate the supported SPDX format and record missing documents or unknown components. +2. For a new advisory, search affected components and versions to identify devices, responsible teams and services that need review. + Reassess stored SBOMs against current advisories even when the installed software has not changed. + An SBOM describes components; it is not a vulnerability verdict or a runtime usage trace. +3. For software approval or redistribution reviews, inspect component provenance and declared licences, then investigate unknown or conflicting entries. + Use the [CSV inventory](#export-a-spreadsheet-inventory) for a review queue, keeping the underlying SPDX evidence. +4. Preview and apply approved updates, then collect fresh inventory, SBOMs and a [vulnerability scan](Homebrew-Vulnerability-Management.md). + Preserve the earlier snapshot with the change record so incident responders can reconstruct what was installed at the time. + +These workflows follow the [CISA guidance on SBOM consumption](https://www.cisa.gov/sites/default/files/2023-12/SECURING%20THE%20SOFTWARE%20SUPPLY%20CHAIN%20RECOMMENDED%20PRACTICES%20FOR%20SOFTWARE%20BILL%20OF%20MATERIALS%20CONSUMPTION%20%282%29.pdf). +For casks and other ecosystems, collect vendor SBOMs or their own inventories separately; Homebrew's formula SBOMs do not cover the whole device. + +### Select updates and verify remediation + +Follow the [vulnerability remediation workflow](Homebrew-Vulnerability-Management.md#select-vulnerable-upgrade-candidates): use `brew outdated --vulnerable --json=v2` to find upgrade candidates, `brew upgrade --vulnerable --dry-run` to preview and `--severity=high` to prioritise high and critical findings while retaining an unfiltered scan. +For an approved version requirement, use `--minimum-version` with `outdated` and `upgrade`; it selects packages below the threshold without pinning the target version. +After applying updates, retain a fresh scan, inventory and SBOMs even if the upgrade failed, and verify the finding before closing the ticket. + +## Build fleet queries and reports + +1. Store successful snapshots centrally, indexed by device, prefix and collection time. +2. Query installed versions, deprecated or disabled packages, available updates and missing team baselines. +3. Join [vulnerability findings](Homebrew-Vulnerability-Management.md) by device, prefix, formula and scanned version. +4. Publish dashboards or CSV exports with incomplete scans and stale devices visible alongside devices reporting no findings. + +The public [formula and cask API](https://formulae.brew.sh/docs/api/) describes available software and contains no device records. + +## Show Homebrew results in MDM inventory + +Use the [MDM reporting steps](Homebrew-Fleet-Management.md#reporting-and-administrator-access) to attach small summaries and collection times to device records while retaining full JSON separately. +The [Jamf Pro](Homebrew-and-Jamf-Pro.md#show-update-needs-in-inventory), [Iru (formerly Kandji)](Homebrew-and-Iru.md#collect-inventory-and-security-reports) and [Microsoft Intune](Homebrew-and-Microsoft-Intune.md#add-inventory-fields-and-collect-reports) guides cover their reporting controls and limits. + +## Keep useful audit evidence + +Retain each management job's device, initiating identity, policy revision, command, timestamps, result and before-and-after inventory in central logs. +Snapshots record state at collection time and MDM logs record management jobs; neither captures every developer command. +Use operating-system auditing if that history is required. +Homebrew's [anonymous analytics](Analytics.md) is not a per-device audit log. + +## Extend inventory beyond Homebrew + +[Homebrew Bundle](Brew-Bundle-and-Brewfile.md#types) can capture supported software with `brew bundle dump --file=team.Brewfile`, including several language-package sources and VS Code extensions. +A Brewfile is a provisioning manifest rather than a complete versioned inventory. +Combine Homebrew records with project lockfiles, environment inventories, browser and IDE extension lists and MDM application discovery. +Collect separately inside containers, virtual machines and WSL environments. diff --git a/docs/Homebrew-Package-Policies.md b/docs/Homebrew-Package-Policies.md new file mode 100644 index 0000000000000..da937e44c9a42 --- /dev/null +++ b/docs/Homebrew-Package-Policies.md @@ -0,0 +1,194 @@ +--- +description: Configure Homebrew package, tap and licence restrictions with brew.env. Build approval workflows and understand endpoint security boundaries. +last_review_date: "2026-10-25" +--- + +# Homebrew Package Policies and Supply Chain Protection + +Homebrew includes central configuration, package restrictions and explicit trust for third-party taps. +Use these features to make your organisation's normal Homebrew workflow follow a reviewed policy. +Your management system distributes the settings and your existing help desk or Git workflow handles approvals. +Operating-system controls remain necessary when the requirement is to prevent an untrusted user from executing software. + +The configuration works on macOS and Linux; cask settings apply only on macOS. +Run the Homebrew commands as the prefix owner. +For root management jobs, use the absolute `brew` path with [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner), for example `/opt/homebrew/bin/brew as-brew-user config` on Apple Silicon. + +- Table of Contents +{:toc} + +## Set central configuration with `brew.env` + +Homebrew reads environment files in this order: + +| Scope | Location | +| ------ | ------------------------------------------------------------------------------------------ | +| System | `/etc/homebrew/brew.env` | +| Prefix | `$HOMEBREW_PREFIX/etc/homebrew/brew.env` | +| User | `~/.homebrew/brew.env`, or the `homebrew/brew.env` file under the configured XDG directory | + +Later files override earlier files. +Set `HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY=1` in `/etc/homebrew/brew.env` to load that file again last, overriding conflicting prefix and user settings. +The user file is resolved using the selected account's home and configuration directory. +See the [environment reference](Manpage.md#environment) for XDG configuration and all available variables. + +1. Create a reviewed `brew.env` in your configuration repository, substituting your help-desk details: + + ```text + HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY=1 + HOMEBREW_FORBIDDEN_OWNER=IT support + HOMEBREW_FORBIDDEN_OWNER_CONTACT=https://support.example.com/homebrew + ``` + + Write literal `NAME=value` lines, without `export` or surrounding shell quotes. + Values can contain spaces, but shell expansion and command substitution are not supported. + Use `1` to enable a setting and omit unwanted settings; `0` is not a general way to disable booleans. +2. Deliver that file to `/var/tmp/homebrew-config/brew.env` with your management system's file or package delivery. + Make this staging directory and file root-owned and writable only by administrators. +3. Install the prepared file as root, readable by the managing account: + + ```sh + /usr/bin/install -d -o root -g "$(/usr/bin/id -gn root)" -m 0755 /etc/homebrew + /usr/bin/install -o root -g "$(/usr/bin/id -gn root)" -m 0644 \ + /var/tmp/homebrew-config/brew.env /etc/homebrew/brew.env + ``` + +4. Inspect the effective settings as the Homebrew owner: + + ```sh + brew config + ``` + + Confirm the expected `HOMEBREW_` settings appear, then follow the [package-policy checks](#deploy-a-central-package-policy) before deploying restrictions more widely. + +Prefix and user files are useful for account-specific defaults. +The prefix owner can normally modify prefix configuration, so use the system file for centrally maintained settings. +These settings control Homebrew behaviour; they do not prevent the owner from modifying Homebrew itself or executing software outside it. + +## Deploy a central package policy + +1. Choose restrictions from the table below and record the policy owner and exception process. +2. Prepare a reviewed `brew.env`, replacing the example packages and help-desk address with your choices: + +```text +HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY=1 +HOMEBREW_FORBIDDEN_FORMULAE=telnet +HOMEBREW_FORBIDDEN_CASKS=transmission +HOMEBREW_FORBIDDEN_TAPS=example/unreviewed +HOMEBREW_FORBID_PACKAGES_FROM_PATHS=1 +HOMEBREW_FORBIDDEN_OWNER=IT support +HOMEBREW_FORBIDDEN_OWNER_CONTACT=https://support.example.com/homebrew +``` + +3. Follow the [central configuration deployment steps](#set-central-configuration-with-brewenv) to install the file on a pilot device. +4. Inspect the effective configuration and test the intended restrictions before assigning more devices. + +Space-separated lists replace earlier values rather than automatically merging across device groups. + +## Choose the restriction that matches the requirement + +| Requirement | Setting or workflow | Scope and limitation | +| -------------------------------- | ------------------------------------------ | --------------------------------------------------------------------- | +| Block named command-line tools | `HOMEBREW_FORBIDDEN_FORMULAE` | Includes formula dependencies; does not remove existing installations | +| Block named applications | `HOMEBREW_FORBIDDEN_CASKS` | Includes cask dependencies; does not block a direct vendor download | +| Block a package source | `HOMEBREW_FORBIDDEN_TAPS` | Use the remote URL when a tap uses a custom remote | +| Refuse local package definitions | `HOMEBREW_FORBID_PACKAGES_FROM_PATHS` | Refuses formula and cask file paths in Homebrew | +| Restrict formula licences | `HOMEBREW_FORBIDDEN_LICENSES` | Uses declared SPDX metadata, including formula dependencies | +| Explain policy failures | `HOMEBREW_FORBIDDEN_OWNER` and its contact | Directs users to the team that owns the restriction | +| Control third-party Ruby loading | `brew trust` and `brew untrust` | Trust is explicit but can be changed by the managing account | + +Inspect effective settings as the Homebrew owner: + +```sh +brew config +``` + +Test restrictions against direct installs and dependencies, since a newly introduced dependency can also block an upgrade. +For licence policies, use SPDX identifiers such as `HOMEBREW_FORBIDDEN_LICENSES=AGPL-3.0-only`; the declared formula licence is not a complete component inventory and casks have no equivalent field. + +## Separate tap trust from package approval + +[Tap trust](Tap-Trust.md) protects against loading non-official package definitions without an explicit trust decision. +Trust individual formulae, casks or commands when that is sufficient; whole-tap trust covers current and future contents. +Official taps are trusted by default. + +Tap trust is not an administrator-controlled allowlist of everything a developer may install. +The managing account can grant trust, including by installing a fully qualified package name. +A Brewfile is also a desired software baseline, not an allowlist: packages absent from it can still be installed. + +For an approved-only catalogue, use a dedicated Homebrew owner and fixed installation actions in your management system. +Users request additions through the [self-service approval workflow](Homebrew-Fleet-Management.md#provide-self-service-software-and-approvals). +Do not grant arbitrary `brew` execution as the dedicated owner merely to implement a self-service button. +Users may still download or run software elsewhere unless separate operating-system controls prevent that. + +## Resolve group policies and exceptions before deployment + +Homebrew does not know MDM groups or exception records. + +1. Resolve group conflicts and approved exceptions into one effective `brew.env` per device. +2. Deploy and verify it using the [central configuration steps](#set-central-configuration-with-brewenv). +3. Find existing restricted packages through [inventory](Homebrew-Inventory-and-SBOM.md); restrictions do not remove them. +4. Review their dependants before approving removals, then collect fresh inventory. + +## Use mirrors without weakening verification + +Homebrew supports `HOMEBREW_API_DOMAIN`, `HOMEBREW_BOTTLE_DOMAIN` and `HOMEBREW_ARTIFACT_DOMAIN` for managed download infrastructure. +Set them in central configuration according to the [environment reference](Manpage.md#environment). +API and bottle mirrors can fall back to their public sources. +`HOMEBREW_ARTIFACT_DOMAIN_NO_FALLBACK=1`, used with `HOMEBREW_ARTIFACT_DOMAIN`, stops artefact downloads when that mirror cannot supply them. + +Git repositories, advisory queries and vendor installers may need separate network access. +Mirrors do not replace device-wide network controls or package verification. + +For compatible casks, `HOMEBREW_CASK_OPTS=--require-sha` requires a checksum. +Use `HOMEBREW_NO_SUDO=1` when your policy forbids Homebrew from invoking privileged installers, and deliver applications that require them through the MDM instead. +Provision private-tap credentials as described in the [fleet guide](Homebrew-Fleet-Management.md#publish-internal-tools-through-private-taps); plain-text `brew.env` files are not a secret-management service. + +### Configure firewall and proxy access + +1. Allow the destinations required by your actual packages and configured mirrors, including HTTPS redirects: + +| Operation | Typical destinations | +| ------------------------- | ------------------------------------------------------------------------------------------------ | +| Package metadata | `formulae.brew.sh` or your configured API mirror | +| Bottles and portable Ruby | `ghcr.io` and its download destinations, or your mirror | +| Homebrew and tap updates | `github.com` and your private Git hosts; SSH if you chose SSH remotes | +| Source and cask downloads | The upstream hosts in the selected packages' URLs and redirects | +| Vulnerability matching | `api.osv.dev`, `formulae.brew.sh`, `raw.githubusercontent.com` and, where needed, `repology.org` | + +This is a starting point, not a complete static domain allowlist. + +2. Test metadata, package and advisory access on a pilot device. + + ```sh + brew update + brew fetch git + brew vulns --json + ``` + +3. Review diagnostics and permit the necessary redirects before expanding deployment. + +Retain diagnostics when a proxy or firewall denies a request; do not disable TLS or checksum verification to make downloads succeed. +Configure proxy settings for the unattended account, not just an administrator's interactive shell; see the [proxy environment variables](Manpage.md#environment). +Your MDM agent has its own network requirements and may not support the same proxy configuration as Homebrew. + +## Apply operating-system execution rules + +Package restrictions govern Homebrew operations; use operating-system controls when the requirement is to prevent execution of software downloaded through any route. +For Macs, follow the [binary execution rules](Homebrew-for-Mac-Admins.md#apply-operating-system-execution-rules), accounting for interpreters, package updates and signing identities. + +## Apply separate controls to other package ecosystems + +Installing a runtime with Homebrew does not route its later downloads through Homebrew's policies or vulnerability scanner. +For project dependencies, use controls such as [`npm audit`](https://docs.npmjs.com/cli/v11/commands/npm-audit/), [pip hash checking](https://pip.pypa.io/en/stable/topics/secure-installs/) and [OSV-Scanner](https://google.github.io/osv-scanner/). +Use your MDM to distribute the applications' own extension controls, such as [Chrome's `ExtensionSettings`](https://support.google.com/chrome/a/answer/9867568?hl=en), [Firefox's `ExtensionSettings`](https://firefox-admin-docs.mozilla.org/reference/policies/extensionsettings/) and [VS Code's allowed-extension policies](https://code.visualstudio.com/docs/enterprise/extensions). +These controls govern supported applications; they do not make Homebrew a scanner for extensions or project dependencies. +Homebrew does not provide a network inspection proxy, runtime malware detector or AI usage monitor. + +## Handle release delays and urgent fixes + +`HOMEBREW_AUTO_UPDATE_SECS` controls metadata refresh timing, not a minimum upstream release age. +Use [staged patch-management jobs](Homebrew-Vulnerability-Management.md) for Homebrew updates. +For language dependencies, [pnpm's minimum release age](https://pnpm.io/settings/dependency-resolution#minimumreleaseage) and [uv's release cutoff](https://docs.astral.sh/uv/reference/settings/#exclude-newer) apply to their own resolvers. + +See [Homebrew Security and Supply Chain](Homebrew-Security-and-Supply-Chain.md) for Homebrew's review, build and distribution protections. diff --git a/docs/Homebrew-Security-and-Supply-Chain.md b/docs/Homebrew-Security-and-Supply-Chain.md index 1611b90e09106..a4b1692612caf 100644 --- a/docs/Homebrew-Security-and-Supply-Chain.md +++ b/docs/Homebrew-Security-and-Supply-Chain.md @@ -2,7 +2,7 @@ description: Homebrew security and supply chain defences, including formula and Cask trust models, checksums, signed metadata, bottles, Gatekeeper, sandboxing and tap trust. redirect_from: - /Supply-Chain-Security -last_review_date: "2026-09-19" +last_review_date: "2026-10-25" --- # Homebrew Security and Supply Chain @@ -14,6 +14,8 @@ This Homebrew security guide explains the recent supply-chain security incidents * Table of Contents {:toc} +For operational guidance, see [vulnerability scanning and patch management](Homebrew-Vulnerability-Management.md), [package policies](Homebrew-Package-Policies.md) and [inventory and SBOM reporting](Homebrew-Inventory-and-SBOM.md). + ## Recent incidents in other ecosystems The npm and PyPI ecosystems have been repeatedly targeted by supply-chain attacks. diff --git a/docs/Homebrew-Vulnerability-Management.md b/docs/Homebrew-Vulnerability-Management.md new file mode 100644 index 0000000000000..db4b6fdd29a6c --- /dev/null +++ b/docs/Homebrew-Vulnerability-Management.md @@ -0,0 +1,167 @@ +--- +description: Scan Homebrew formulae for known vulnerabilities, export JSON findings and automate verified security updates with Homebrew commands and your MDM. +last_review_date: "2026-10-25" +--- + +# Homebrew Vulnerability Scanning and Patch Management + +Use `brew vulns` to check Homebrew formulae for known vulnerabilities, then use `brew upgrade` to install available fixes. +Your scheduler or MDM can run them across devices and retain the results for a central patch-management workflow. +The scanner checks formulae; it does not scan casks or every package installed by other tools. + +Run these commands as the Homebrew owner on macOS or Linux, with `brew` and any required tools on `PATH`. +For root management jobs, use the absolute path with [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner), for example `/opt/homebrew/bin/brew as-brew-user` in place of `brew` on Apple Silicon. + +- Table of Contents +{:toc} + +## Scan installed formulae + +1. Refresh metadata and run an initial scan. + +```sh +brew update +brew vulns --list-skipped +``` + +With no formula arguments, `brew vulns` checks installed formulae. +It queries the [Open Source Vulnerabilities database](https://osv.dev/) using supported source identities and versions. +It can account for fixes supplied by formula patches, rather than assuming that every unchanged upstream version remains vulnerable. +Use `--no-ignore-patches` when investigating findings that those patches resolve. + +2. If investigating a single package, scan it and its dependencies. + +```sh +brew vulns --deps git +``` + +3. For a baseline review, scan formula entries in a reviewed Brewfile. + +```sh +brew vulns --brewfile=Brewfile --deps +``` + +A Brewfile scan covers its formula entries, not its casks, language-package entries or every installed package omitted from the file. +For uninstalled formulae, the scan assesses the available formula definition rather than an installed artefact. + +## Capture findings without losing errors + +`brew vulns` returns a non-zero status for open findings and for some incomplete-scan conditions. +A non-zero status alone does not distinguish a vulnerability from an operational failure. +Conversely, a zero status does not mean every package was scanned: unsupported-source skips can remain in the report. + +1. Create a protected [report directory](Homebrew-Inventory-and-SBOM.md#export-installed-software-as-json). +2. Run this capture step from that directory. + +```bash +#!/bin/bash +set -euo pipefail + +scan_status=0 +brew vulns --json > homebrew-vulns.json 2> homebrew-vulns.stderr || scan_status=$? +printf '%s\n' "${scan_status}" > homebrew-vulns.status +exit "${scan_status}" +``` + +3. Retain the files even when the job exits unsuccessfully. +4. Validate the JSON before importing it and retain standard error even when JSON parsing succeeds. + +Each `findings` entry identifies the formula, scanned version, source repository, open vulnerabilities and vulnerabilities resolved by formula patches. +The report also describes scan coverage: + +| Field | Meaning | +| ----------------------- | ---------------------------------------------------------------------------------- | +| `checked` | Number of formula targets queried, including targets without findings | +| `complete` | Whether all selected targets were assessed without the coverage gaps listed below | +| `skipped_formulae` | Formulae without a supported source identity | +| `outdated_without_sbom` | Older installations assessed using current-recipe data because evidence is missing | +| `unscanned_formulae` | Installed formula names mapped to `untrusted_tap` or `resolution_error` | + +`complete` describes the selected formula scope; severity and fix filters can still exclude findings. +Network failures can prevent JSON output entirely. +An old installation without usable source evidence may be assessed using current-recipe data, with a warning and failing status; that result does not establish the installed version's vulnerability status. + +## Prioritise without hiding unresolved risk + +1. Retain the unfiltered report and its coverage fields. +2. Filter a remediation queue for the same installation: + +```sh +brew vulns --json --severity=high --fix-available +``` + +`--severity=high` includes high and critical findings. +Unknown severity does not meet that threshold, so retain an unfiltered scan as well. +`--fix-available` means an upstream released fix is known; it does not guarantee that Homebrew already provides that version or that the device can install it. +Use `--no-fix-available` to investigate findings without an upstream released fix, including those with only an unreleased patch. +See the [command reference](Manpage.md#vulns-options-formula-) for all fix-type filters. + +## Select vulnerable upgrade candidates + +`brew outdated --vulnerable` uses the same OSV scanner to filter installed formulae that have an update available. + +1. Export the upgrade candidates, then preview the plan. + +```sh +brew outdated --vulnerable --severity=high --json=v2 +brew upgrade --vulnerable --severity=high --dry-run +``` + +Both commands imply `--formula` and reject `--cask`. +Omit `--severity` to include findings of every severity, including unknown severity. +Findings resolved by a formula patch are excluded using the same installed-version rules as `brew vulns`. +Pinned packages remain subject to normal pin behaviour: `outdated` can report them and `upgrade` leaves them pinned. + +If any outdated candidate has an unsupported source or lacks reliable installed-source evidence, selection fails before upgrades begin. +Resolve the coverage gap or review specific named candidates instead; a network failure also stops selection. +This check covers the candidates being selected, not every installed package or retained keg. +An empty selection upgrades nothing. + +An available update is not proof that a vulnerability is fixed in that release. +`--vulnerable` selects affected installed formulae; it does not promise a vulnerability-free target version or restrict dependency upgrades to security fixes. +Keep a full `brew vulns --json` report to track findings with no available Homebrew update. + +## Apply and verify updates + +1. Apply the reviewed severity-based plan, then assess the result even if the upgrade fails. + Run these as separate management steps and retain both results. + +```sh +brew upgrade --vulnerable --severity=high --yes +brew vulns --json +``` + +Use explicit formula arguments when a rollout approves only a subset of candidates. +The scan is repeated when the upgrade command runs, so review changing advisory data and package metadata as part of the rollout. + +Homebrew may also upgrade dependencies and dependants, so review the complete plan. + +2. If the requirement is an approved minimum version, use the threshold instead. + +```sh +brew outdated --minimum-version=2.50.1 git +brew upgrade --minimum-version=2.50.1 --dry-run git +brew upgrade --yes --minimum-version=2.50.1 git +brew list --versions git +``` + +The version above is an example policy threshold, not a current security recommendation. +The command upgrades an installed package only when it is below the threshold and installs the available version, not necessarily that exact version. +It does not install a missing package, override pins or guarantee that a sufficiently new release is available. +Verify the resulting installed version and rescan after upgrading. + +## Automate patching through your management system + +Use the [MDM deployment and scheduling guides](Homebrew-Fleet-Management.md#integrate-with-your-management-system) to assign these commands to a pilot group, then expand after reviewing the results. +Retain the pre-upgrade scan, upgrade status and post-upgrade scan separately, including after failed upgrades; close findings only after verification and report offline devices, pins, missing coverage and unavailable fixes separately. +Restart affected applications or services when needed and review retained older kegs; removing a device from a job's scope does not undo an upgrade. + +## Understand the limits of a clean scan + +An empty findings array means no matches for the assessed targets and filters, not that the device is free of vulnerabilities or malware. +Review the coverage fields above and reconcile unresolved installations with inventory. +Untrusted taps are not automatically evaluated; advisory matching can also miss bundled components or downstream changes. + +For casks, combine `brew outdated --cask --greedy`, application inventory and upstream security advisories. +Project dependencies and extensions need ecosystem-specific scanners. +See [package policies](Homebrew-Package-Policies.md) for complementary controls. diff --git a/docs/Homebrew-and-Iru.md b/docs/Homebrew-and-Iru.md new file mode 100644 index 0000000000000..2f4afcc276e50 --- /dev/null +++ b/docs/Homebrew-and-Iru.md @@ -0,0 +1,67 @@ +--- +description: Deploy Homebrew with Iru, formerly Kandji, using Custom Apps, Brewfile audit and remediation scripts, scheduled updates and Self Service. +last_review_date: "2026-10-25" +--- + +# Manage Homebrew with Iru (formerly Kandji) + +Use Iru's macOS Library Items to install Homebrew, check team software and run approved maintenance. +Start with an Apple Silicon Mac in a `Homebrew Pilot` Blueprint or Assignment Map. + +## Deploy Homebrew and its configuration + +1. Provision the managing account using your account workflow or Iru's [Create User Accounts parameter](https://docs.iru.com/en/endpoint/blueprints/parameters/create-user-accounts). + Follow the [shared account and home-directory checks](Homebrew-for-Mac-Admins.md#initial-provisioning); the account must exist before installation. +2. Add the approved Homebrew `.pkg` as a **Mac Custom App** Library Item. + Use a pre-install script for the account checks and `HOMEBREW_PKG_USER` configuration, stopping on failure. + Follow [Iru's Custom App configuration](https://docs.iru.com/en/endpoint/library/library-items-profiles/configure-the-custom-apps-library-item) and assign the pilot Blueprint. +3. Deliver [central configuration](Homebrew-Package-Policies.md#set-central-configuration-with-brewenv) and the [team Brewfile](Homebrew-Fleet-Management.md#install-default-software-for-each-team). +4. Verify the owner and working Homebrew command using the [post-install checks](Homebrew-for-Mac-Admins.md#initial-provisioning), then inspect the Custom App's device status before expanding assignments. + +## Check and install the team baseline + +1. Create a **Custom Script** Library Item named `Homebrew baseline` and choose **Run daily** for a recurring baseline check. + In **Audit Script**, use the following check after deploying the Brewfile. + [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) switches Iru's root script to the prefix owner and its home directory: + + ```bash + #!/bin/bash + set -euo pipefail + + test -x /opt/homebrew/bin/brew + test -r /Library/Management/Homebrew/Brewfile + /opt/homebrew/bin/brew as-brew-user bundle check \ + --no-upgrade --file=/Library/Management/Homebrew/Brewfile + ``` + +2. Set **Remediation Script** to the [Brewfile installation job](Homebrew-Fleet-Management.md#install-default-software-for-each-team). + Keep its prerequisite checks: a failed audit can mean missing Homebrew or an unreadable file, not just missing packages. +3. Assign the pilot Blueprint and inspect the item's status and recorded output. + A non-zero audit result triggers remediation; investigate failures before expanding deployment. + See [Iru's Custom Scripts reference](https://docs.iru.com/en/endpoint/library/library-items-profiles/custom-scripts-overview). + +## Collect inventory and security reports + +1. Add a **Custom Script** Library Item for the [inventory collection job](Homebrew-Inventory-and-SBOM.md#export-installed-software-as-json), with daily execution and pilot assignment. + Replace `brew` in shared examples with `/opt/homebrew/bin/brew as-brew-user`: [this wrapper](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) runs Homebrew as its owner from Iru's root script. + Use `/opt/homebrew/bin/jq` when processing JSON and include `jq` in the baseline. +2. Collect a [vulnerability scan with its diagnostics and status](Homebrew-Vulnerability-Management.md#capture-findings-without-losing-errors) and inspect the item's recorded output. + A non-zero scan status can indicate findings or an operational failure; inspect both the report and its coverage. +3. Upload full JSON and available [SBOMs](Homebrew-Inventory-and-SBOM.md#collect-formula-software-bills-of-materials) through your organisation's collector with device identity and collection time. + Custom Script output does not automatically populate Iru's built-in vulnerability views. + Track stale devices and collection failures separately from successful scans without findings. + +## Schedule updates and offer approved tools + +1. Add a separate Custom Script for the [reviewed maintenance job](Homebrew-Fleet-Management.md#schedule-updates-and-staged-rollouts), with daily execution and pilot assignment. + Avoid concurrent update and baseline jobs on the same prefix. +2. Review script output and fresh [inventory and security reports](#collect-inventory-and-security-reports) before assigning more devices. + A successful remediation status alone does not establish that security findings are resolved. +3. For an approved installation action, create a Custom Script with **Run on-demand from Self Service**, using the [fixed installation example](Homebrew-Fleet-Management.md#provide-self-service-software-and-approvals). +4. Test Self Service as a standard user and confirm the new package appears in inventory. + +## Limit administrator access + +1. Assign [Iru team roles](https://docs.iru.com/en/iru/access/team-member-role-permissions) for report readers, operators and Library Item maintainers. +2. Verify a restricted account can perform its intended tasks without editing root scripts or expanding their assignment. +3. For multiple customers, use separate supported tenant boundaries and test report isolation as described in [shared administration guidance](Homebrew-Fleet-Management.md#reporting-and-administrator-access). diff --git a/docs/Homebrew-and-Jamf-Pro.md b/docs/Homebrew-and-Jamf-Pro.md new file mode 100644 index 0000000000000..95216fb6dd91f --- /dev/null +++ b/docs/Homebrew-and-Jamf-Pro.md @@ -0,0 +1,64 @@ +--- +description: Deploy Homebrew with Jamf Pro policies, report package updates with extension attributes and offer approved tools through Self Service. +last_review_date: "2026-10-25" +--- + +# Manage Homebrew with Jamf Pro + +Use Jamf Pro's package delivery, policies and inventory to manage Homebrew on enrolled Apple Silicon Macs. +Start with one computer in a `Homebrew Pilot` group and a reviewed [team Brewfile](Homebrew-Fleet-Management.md#install-default-software-for-each-team). + +## Deploy Homebrew and the baseline + +1. Complete [account provisioning and installer configuration](Homebrew-for-Mac-Admins.md#initial-provisioning) in a prerequisite policy. + Verify the account, writable home and `HOMEBREW_PKG_USER` configuration before assigning the package policy. +2. Upload the approved Homebrew `.pkg` under **Settings > Computer management > Packages**. + Create a package policy scoped only to pilot devices whose prerequisite checks succeeded. + Script priority controls ordering; use policy scope to gate deployment on the prerequisite results. + Follow [Jamf's package policy instructions](https://learn.jamf.com/r/en-US/jamf-pro-documentation-current/Deploying_a_Package_Using_a_Policy). +3. Deliver [central configuration](Homebrew-Package-Policies.md#set-central-configuration-with-brewenv) and the Brewfile. + Use an **After** script for the [Brewfile installation job](Homebrew-Fleet-Management.md#install-default-software-for-each-team) once the files are present. +4. Review the policy log and [verify the installed owner and version](Homebrew-for-Mac-Admins.md#initial-provisioning). + Require these checks before expanding the policy scope; a package receipt alone is insufficient. + +## Show update needs in inventory + +1. Deploy `jq` in the baseline and refresh Homebrew metadata in the maintenance policy. +2. Add a script [computer extension attribute](https://learn.jamf.com/r/en-US/jamf-pro-documentation-current/Computer_Extension_Attributes) named `Homebrew outdated formulae`, with data type **String**. + The script below uses [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) to query the prefix owner's installation from Jamf's root job: + + ```bash + #!/bin/bash + set -o pipefail + + if count=$(/opt/homebrew/bin/brew as-brew-user outdated --json=v2 | + /opt/homebrew/bin/jq -er '.formulae | arrays | length'); then + printf '%s\n' "${count}" + else + printf 'unknown\n' + fi + ``` + +3. Run an inventory update and inspect the device's attribute. + Expect a count such as `3`; a failed command must produce `unknown`, not `0`. +4. Create a Smart Computer Group where the attribute is neither `0` nor `unknown`, and a separate group for `unknown`. + Check last inventory time to distinguish current results from stale devices. + Retain full [inventory, SBOM and vulnerability reports](Homebrew-Inventory-and-SBOM.md) separately; an outdated count is not a security finding. + For these shared collection examples, use the same absolute paths and `as-brew-user` wrapper from Jamf's root jobs. + +## Schedule updates and offer approved installations + +1. Under **Computers > Policies**, create a policy with the [reviewed update job](Homebrew-Fleet-Management.md#schedule-updates-and-staged-rollouts) in its **Scripts** payload. + Choose a recurring check-in trigger, execution frequency and pilot scope using [Jamf's script policy controls](https://learn.jamf.com/r/en-US/jamf-pro-documentation-current/Running_Scripts_Using_a_Policy). +2. Add an inventory update after maintenance, inspect failures and expand to the affected group after the pilot succeeds. + For security work, follow the [scan, select, upgrade and rescan workflow](Homebrew-Vulnerability-Management.md); retain the final scan even when upgrading fails. +3. Create a separate policy with a fixed [approved installation action](Homebrew-Fleet-Management.md#provide-self-service-software-and-approvals) and enable **Self Service**. + Test it with a standard user, then refresh inventory. +4. Collect large report files through your existing log collection system; Jamf policy logs truncate at 25 KB. + +## Limit administrator access + +1. Configure [Jamf accounts, groups and privilege sets](https://learn.jamf.com/r/en-US/jamf-pro-documentation-current/Jamf_Pro_User_Accounts_and_Groups) for inventory readers, deployment operators and script maintainers. +2. Test each role with a restricted account, including access to reports and policy scope. +3. For multiple customers, use supported site or tenant boundaries and test cross-customer isolation. + A Smart Computer Group is not an access-control boundary; see [shared administration guidance](Homebrew-Fleet-Management.md#reporting-and-administrator-access). diff --git a/docs/Homebrew-and-Microsoft-Intune.md b/docs/Homebrew-and-Microsoft-Intune.md new file mode 100644 index 0000000000000..cf2e702c2e579 --- /dev/null +++ b/docs/Homebrew-and-Microsoft-Intune.md @@ -0,0 +1,80 @@ +--- +description: Deploy Homebrew on macOS with Microsoft Intune, run maintenance scripts as the Homebrew owner and collect custom inventory attributes. +last_review_date: "2026-10-25" +--- + +# Manage Homebrew with Microsoft Intune + +Use Intune's macOS management agent for Homebrew installation scripts, maintenance and custom attributes. +The following steps use Apple Silicon Macs and an Entra device group named `Homebrew Pilot`. + +## Deploy Homebrew and the baseline + +Intune's [PKG app detection](https://learn.microsoft.com/en-us/intune/app-management/deployment/add-unmanaged-pkg-macos#step-4--detection-rules) uses application bundle identifiers. +Homebrew has no application bundle, so use a root installation script and verify its owner and commands directly. + +1. Follow [account provisioning and installer configuration](Homebrew-for-Mac-Admins.md#initial-provisioning). + Put the account checks and installer configuration in the installation script before the download and installation commands below, with `set -euo pipefail` so failures stop deployment. +2. Approve a Homebrew `.pkg` release and record its URL and SHA-256 checksum. + Replace both placeholders below with the values you reviewed, then add these commands to the same script: + + ```bash + umask 077 + pkg_dir=$(/usr/bin/mktemp -d /var/tmp/homebrew-installer.XXXXXX) + trap '/bin/rm -rf "${pkg_dir}"' EXIT + /usr/bin/curl --fail --location --output "${pkg_dir}/Homebrew.pkg" \ + 'APPROVED_PKG_URL' + printf '%s %s\n' 'APPROVED_SHA256' "${pkg_dir}/Homebrew.pkg" | + /usr/bin/shasum -a 256 --check - + /usr/sbin/installer -pkg "${pkg_dir}/Homebrew.pkg" -target / + ``` + +3. Assign the installation script to `Homebrew Pilot` using the [script settings below](#assign-maintenance-scripts), with **Run script as signed-in user** set to **No** and a frequency of **Not configured** for a single run. + Use the [post-install verification commands](Homebrew-for-Mac-Admins.md#initial-provisioning) before assigning more devices. +4. Deliver [central configuration](Homebrew-Package-Policies.md#set-central-configuration-with-brewenv) and the [team Brewfile](Homebrew-Fleet-Management.md#install-default-software-for-each-team), then assign the baseline job. + Separately assigned scripts can run in parallel, so require successful prerequisite results before assigning dependent jobs. + +## Assign maintenance scripts + +1. Open **Devices > By platform > macOS > Manage devices > Scripts > Add**. +2. Upload the [Brewfile installation job](Homebrew-Fleet-Management.md#install-default-software-for-each-team), set **Run script as signed-in user** to **No** and assign `Homebrew Pilot`. + The examples use [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) to switch from root to the prefix owner without requiring a signed-in user. +3. Review the result, then assign the [approved maintenance job](Homebrew-Fleet-Management.md#schedule-updates-and-staged-rollouts) with a suitable frequency and retry count. + Prevent overlapping jobs on the same prefix. +4. Collect fresh results after each run: the portal's script status is not a history of every recurring execution. + Use custom attributes and retained reports below. + +Microsoft's [macOS script reference](https://learn.microsoft.com/en-us/intune/device-management/tools/run-shell-scripts-macos) documents prerequisites, scheduling and reporting limits. + +## Add inventory fields and collect reports + +1. Under macOS **Organize devices > Custom attributes for macOS**, add `Homebrew outdated formulae` with type **Integer**. +2. Upload this script, then assign the pilot group. + Include `jq` in the baseline and refresh metadata in your maintenance job first. + [`as-brew-user`](Homebrew-for-Mac-Admins.md#run-management-commands-as-the-owner) queries the installation as its owner from Intune's root job: + + ```bash + #!/bin/bash + set -euo pipefail + + /opt/homebrew/bin/brew as-brew-user outdated --json=v2 | + /opt/homebrew/bin/jq -er '.formulae | arrays | length' + ``` + + It prints the count alone; `pipefail` preserves collection failures separately from a successful zero count. + An outdated count is not a vulnerability count. +3. Review **Device status** and the attribute's age; custom attributes run every eight hours. + Do not assume these attributes can serve as Entra dynamic-group criteria. +4. Save full [inventory and SBOM reports](Homebrew-Inventory-and-SBOM.md) through your organisation's collector. + Use the same absolute paths and `as-brew-user` wrapper when adapting those shared examples for root jobs. + For investigations, use **Collect logs** and an allowed archive format such as `.zip` for JSON files. +5. Select affected devices from current findings, assign the [approved remediation](Homebrew-Vulnerability-Management.md#automate-patching-through-your-management-system) and collect a fresh scan before closing the finding. + +## Control assignments and administrator access + +1. Use administrator-assigned scripts for Homebrew jobs. + Company Portal's **Available** app assignment delivers applications; it is not a general shell-script button. + A self-service Homebrew action needs a tested package and detection design. +2. Assign [Intune roles, scope groups and scope tags](https://learn.microsoft.com/en-us/intune/fundamentals/role-based-access-control/overview) so report readers cannot edit or assign root scripts. +3. Test a restricted account against another group's or customer's devices before granting access. + Follow the [shared access-control guidance](Homebrew-Fleet-Management.md#reporting-and-administrator-access) for customer separation and audit evidence. diff --git a/docs/Homebrew-for-Mac-Admins.md b/docs/Homebrew-for-Mac-Admins.md index 278c5f72fb119..50a877ad7648b 100644 --- a/docs/Homebrew-for-Mac-Admins.md +++ b/docs/Homebrew-for-Mac-Admins.md @@ -1,12 +1,12 @@ --- -last_review_date: "2026-09-21" +last_review_date: "2026-10-25" description: Deploy and manage Homebrew with MDM, non-admin accounts and central configuration. --- # Homebrew for Mac Admins: MDM and Non-Admin Accounts This guide covers provisioning Homebrew through MDM and running it as a standard account or a dedicated Homebrew account. -It also covers central configuration, software restrictions and unattended maintenance with tools such as Jamf and Munki. +For dashboard setup, follow the [Jamf Pro](Homebrew-and-Jamf-Pro.md), [Iru (formerly Kandji)](Homebrew-and-Iru.md), [Microsoft Intune](Homebrew-and-Microsoft-Intune.md) or [other provider instructions](Homebrew-Fleet-Management.md#other-management-systems). The examples use the Apple Silicon prefix `/opt/homebrew`; see [Installation](Installation.md) for platform requirements. ## Choose the managing account @@ -25,11 +25,102 @@ Homebrew provides no security guarantees for installations where users with writ ## Initial provisioning -Create the managing account and its home directory before installing Homebrew. -For MDM deployment, we recommend the [official macOS `.pkg` installer and its `HOMEBREW_PKG_USER` setting](Installation.md#installation). -The selected account must exist before installation; this also supports installation at the login window. -Use the `.pkg` installer if sudo is unavailable on the host. -On Apple Silicon, casks and bottles can be installed without developer tools; install them when you need to build formulae from source. +The following example provisions a new Apple Silicon Mac for a dedicated standard account named `brewadmin`. +For a user-owned installation, substitute the existing user's short name and home directory throughout. +Run preparation commands as root through your management system; do not change the ownership of an existing installation without reviewing its packages and services first. + +1. Create the account through your organisation's account-provisioning workflow before assigning the Homebrew package. + For a local pilot, an administrator can use **System Settings > Users & Groups > Add User**. + Use these example values, with a unique password supplied through your normal credential-management system: + + | Setting | Example value | + | ------------ | ---------------------- | + | Account type | Standard | + | Full name | Homebrew Management | + | Short name | `brewadmin` | + | Home | `/Users/brewadmin` | + | Login shell | `/bin/zsh` | + + Do not embed a shared password in a deployment script or job log. + The account needs no administrator privileges, sudo access or interactive login session. +2. Verify the account exists and its configured home is correct, then create that directory if your provisioning workflow has not already done so: + + ```bash + /usr/bin/id brewadmin + /usr/bin/dscl . -read /Users/brewadmin NFSHomeDirectory UserShell + /usr/bin/install -d -o brewadmin -g "$(/usr/bin/id -gn brewadmin)" \ + -m 0750 /Users/brewadmin + /usr/bin/sudo -H -u brewadmin /bin/test -w /Users/brewadmin + ``` + + Expect `NFSHomeDirectory: /Users/brewadmin` and a successful writable-directory check. + Stop deployment if either check fails; a directory alone does not create an account. +3. Select that account for the installer, then set the required ownership, mode and ACL state: + + ```sh + /usr/bin/defaults write /var/tmp/.homebrew_pkg_user HOMEBREW_PKG_USER brewadmin + /usr/sbin/chown root:wheel /var/tmp/.homebrew_pkg_user.plist + /bin/chmod 600 /var/tmp/.homebrew_pkg_user.plist + /bin/chmod -N /var/tmp/.homebrew_pkg_user.plist + /usr/bin/defaults read /var/tmp/.homebrew_pkg_user HOMEBREW_PKG_USER + /bin/ls -le /var/tmp/.homebrew_pkg_user.plist + ``` + + Expect `brewadmin`, owner `root`, group `wheel` and permissions `-rw-------` without a `+` or ACL entries. + The file must be a regular file, not a symbolic link. + The [installer configuration requirements](Installation.md#installation) explain validation and fallback behaviour: an invalid file can select the console user instead. +4. Download the official `.pkg` from [Homebrew's releases](https://github.com/Homebrew/brew/releases/latest), approve that version and upload it to your management system's package delivery workflow. + Assign it only after steps 1–3 have succeeded. + For a local pilot with the approved package saved as `/Library/Management/Homebrew/Homebrew.pkg`, run: + + ```sh + /usr/sbin/installer -pkg /Library/Management/Homebrew/Homebrew.pkg -target / + ``` + + The selected account can own the installation at the login window; nobody needs to be logged in. + The package does not require an existing Git installation for basic bottle and cask use. + [Install Git for management jobs](#install-git-for-management-jobs) before running the baseline or updates; developer tools are also needed when building formulae from source. +5. Verify the prefix owner, then use [`as-brew-user`](#run-management-commands-as-the-owner) to run Homebrew as that account with its home and environment: + + ```sh + /usr/bin/stat -f '%Su' /opt/homebrew + /opt/homebrew/bin/brew as-brew-user --version + /opt/homebrew/bin/brew as-brew-user config + ``` + + Expect `brewadmin` as owner and a successful Homebrew version report. + Retain the installer output and these checks before expanding the deployment. + Continue with [central configuration](#set-central-configuration-with-brewenv) and a [team Brewfile](Homebrew-Fleet-Management.md#install-default-software-for-each-team). + +### Install Git for management jobs + +Install Apple's Command Line Tools (CLT) to provide Git before running `brew update`, baseline jobs or the shell installer. +A working Git from an existing Xcode installation also suffices. +The presence of `/usr/bin/git` alone is insufficient: without developer tools, it can be a macOS installation prompt stub that Homebrew deliberately avoids. + +1. Choose an installation method: + - **Interactive setup:** run `/usr/bin/xcode-select --install` in Terminal, accept the dialogue and wait for installation to finish. + This selects a compatible release without maintaining a package, but requires user interaction and does not let you choose a specific version. + - **Unattended MDM deployment:** sign in to [Apple Developer downloads](https://developer.apple.com/download/all/?q=command%20line%20tools), download an approved CLT release compatible with the target macOS and mount its disk image to obtain the `.pkg`. + Deploy that package through your MDM as root. + This supports deployment without a logged-in user and staged rollout of a tested version, but you must maintain the package and its macOS compatibility. +2. For a local package test, save the approved installer as `/Library/Management/Homebrew/CommandLineTools.pkg` and run as root: + + ```sh + /usr/sbin/installer -pkg /Library/Management/Homebrew/CommandLineTools.pkg -target / + ``` + +3. After either installation method, verify the selected developer directory and execute Git: + + ```sh + /usr/bin/xcode-select --print-path + /usr/bin/xcrun git --version + ``` + + Require successful verification before assigning Homebrew jobs. + Recheck compatibility after macOS upgrades and keep CLT updated through Software Update or your managed package workflow; see [Apple's installation and update instructions](https://developer.apple.com/documentation/xcode/installing-the-command-line-tools/). + +### Alternative shell installer Alternatively, an MDM agent running as root can use the shell installer to provision Homebrew for an existing standard account. The shell installer requires an existing usable Git; use the `.pkg` installer on hosts without one. @@ -55,13 +146,26 @@ Use the installer's printed `brew shellenv` instructions for interactive shells ## Run management commands as the owner -When your process already runs as the managing account, invoke `brew` normally. -A management agent running as root can select the prefix owner explicitly: +Management agents normally execute scripts as root, but Homebrew package operations must run as the non-root account that owns the prefix. +`as-brew-user` selects that owner, switches accounts when necessary and supplies its home directory and a clean environment. +It also works when the caller is already the owner, so the management examples use it consistently. +An unrelated standard account still needs permission to switch users. -```sh -/opt/homebrew/bin/brew as-brew-user install --yes wget -/opt/homebrew/bin/brew as-brew-user update -``` +A root job executes the Homebrew launcher before switching accounts, so only use this workflow when the prefix owner is trusted with that execution. +Use a dedicated managing account when end users must not control code run by the root job. + +1. Use the absolute path `/opt/homebrew/bin/brew` on Apple Silicon: a management job may not have Homebrew on `PATH`. +2. Put `as-brew-user` before the Homebrew command and its arguments. + For example, refresh metadata, then install an approved tool without interactive prompts: + + ```sh + /opt/homebrew/bin/brew as-brew-user update + /opt/homebrew/bin/brew as-brew-user install --yes wget + ``` + +3. Retain standard output, standard error and the exit status in the management job. + Extra account-switching diagnostics go to standard error; JSON remains on standard output. + Shell redirection such as `> report.json` runs as the calling account, so a root job can save reports outside the managing account's home. `as-brew-user` works without an active console login and rejects a root-owned prefix. It uses the owner's home directory and a clean environment. @@ -84,118 +188,19 @@ Use those files for persistent management settings; exporting a variable in the ## Set central configuration with `brew.env` -Homebrew reads environment files in this order: - -| Scope | Location | -| ------ | ------------------------------------------------------------------------------------------ | -| System | `/etc/homebrew/brew.env` | -| Prefix | `/opt/homebrew/etc/homebrew/brew.env` | -| User | `~/.homebrew/brew.env`, or the `homebrew/brew.env` file under the configured XDG directory | - -Later files override earlier files. -Set `HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY=1` in `/etc/homebrew/brew.env` to load that file again last, overriding conflicting prefix and user settings. -The user file is resolved using the selected account's home and configuration directory. -See the [environment reference](Manpage.md#environment) for XDG configuration and all available variables. - -For example, deploy this file as `/etc/homebrew/brew.env`: - -```text -HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY=1 -HOMEBREW_FORBIDDEN_OWNER=IT support -HOMEBREW_FORBIDDEN_OWNER_CONTACT=https://support.example.com/homebrew -``` - -Write literal `NAME=value` lines, without `export` or surrounding shell quotes. -Values can contain spaces, but shell expansion and command substitution are not supported: `$HOME` and `$(id -gn)` would remain literal text. -Use `1` to enable a setting and omit it when it is not wanted. -Some booleans test whether a value is set, so `0` is not a general way to disable them. - -Manage the system file and its directory as root, readable by the managing account and writable only by administrators. -For example, deploy a prepared file with: - -```sh -/usr/bin/install -d -o root -g wheel -m 0755 /etc/homebrew -/usr/bin/install -o root -g wheel -m 0644 /path/to/brew.env /etc/homebrew/brew.env -``` - -Prefix and user files are useful for account-specific defaults. -The prefix owner can normally modify prefix configuration, so use the system file for centrally maintained settings. -These settings control Homebrew behaviour; they do not prevent the owner from modifying Homebrew itself or executing software outside it. +Follow the [central configuration steps](Homebrew-Package-Policies.md#set-central-configuration-with-brewenv) to deploy `/etc/homebrew/brew.env` and verify settings as the managing account. +The same configuration format supports Macs and Linux systems; system settings can take priority over prefix and user defaults. ## Restrict software and package sources -Choose restrictions that match your deployment rather than enabling every setting. -Lists below are space-separated values in `brew.env`. - -| Variable | Behaviour | -| ------------------------------------- | ------------------------------------------------------------------------ | -| `HOMEBREW_FORBID_PACKAGES_FROM_PATHS` | Refuses formulae and casks supplied through file paths. | -| `HOMEBREW_FORBIDDEN_FORMULAE` | Refuses listed formulae, including when required as dependencies. | -| `HOMEBREW_FORBIDDEN_CASKS` | Refuses listed casks, including when required as dependencies. | -| `HOMEBREW_FORBIDDEN_TAPS` | Refuses installation from listed taps, including dependencies. | -| `HOMEBREW_FORBIDDEN_LICENSES` | Refuses formulae with listed SPDX licences, including dependencies. | -| `HOMEBREW_FORBIDDEN_OWNER` | Names the person or team responsible for restrictions in error messages. | -| `HOMEBREW_FORBIDDEN_OWNER_CONTACT` | Adds contact information to restriction messages. | - -For tap restrictions, a `user/repository` entry matches its default GitHub remote; use the remote URL for a custom remote. -Restrictions do not remove software that is already installed. - -Use [tap trust](Tap-Trust.md) to explicitly trust required third-party formulae, casks or commands. -Trusting an entire tap allows its current and future contents to run as the managing account. -Tap trust and the restriction variables have different purposes; neither is a substitute for operating-system application controls. +Use [package policies](Homebrew-Package-Policies.md) to restrict packages, taps, local definitions and formula licences, with a named contact for exceptions. +The guide explains tap trust, group policy conflicts and the limits of controls enforced by the package manager. ## Manage software and updates -A centrally maintained [Brewfile](Brew-Bundle-and-Brewfile.md) can describe the software to install: - -```sh -/opt/homebrew/bin/brew as-brew-user bundle install --file=/Library/Management/Homebrew/Brewfile -``` - -Make the Brewfile readable by the managing account and writable by its maintainers. -Installing a Brewfile does not automatically remove packages omitted from it; review `brew bundle cleanup` before using its removal options. -Run management jobs serially and collect both their output and exit status. -If logging through a shell pipeline, enable `pipefail` so a successful logger does not hide a failed Homebrew command. - -Homebrew's automatic updates refresh Homebrew and package metadata; `brew upgrade` upgrades installed software. -If you set `HOMEBREW_NO_AUTO_UPDATE=1`, schedule explicit `brew update` runs to keep metadata current. -`HOMEBREW_NO_INSTALL_UPGRADE=1` prevents `brew install` from upgrading an already-installed package, while `HOMEBREW_NO_INSTALL_CLEANUP=1` allows you to schedule cleanup separately. -Disabling these automatic actions creates maintenance work for your management workflow. - -For a minimum-version policy on an installed package, use your approved version threshold, for example: - -```sh -/opt/homebrew/bin/brew as-brew-user upgrade --yes --minimum-version=2.50.1 git -``` - -The threshold decides whether an upgrade is needed; it does not pin the package to that exact version. -Account for uninstalled or pinned packages in your management workflow and check the resulting installed version. -Use the [command reference](Manpage.md) to check options available in the Homebrew version deployed to your Macs. - -### Vulnerability updates - -Run `brew vulns` without formula names to check all installed formulae for known vulnerabilities: - -```sh -/opt/homebrew/bin/brew as-brew-user update -/opt/homebrew/bin/brew as-brew-user vulns --list-skipped -``` - -The scan returns a non-zero status when it finds unresolved vulnerabilities or cannot reliably scan some installed formulae. -Keep its output and exit status; review skipped packages as well as findings. -Casks are not scanned. -Use `--json` for management reports, `--severity=high` to focus on high and critical findings or `--fix-available` to show findings with a released fix. - -To apply available upgrades across the installation, including vulnerable formulae, then check again: - -```sh -/opt/homebrew/bin/brew as-brew-user upgrade --yes -/opt/homebrew/bin/brew as-brew-user vulns --list-skipped -``` - -For selective remediation, pass the affected formula names from the scan to `brew upgrade --yes --formula`. -Pinned formulae and vulnerabilities without a fix in the available Homebrew version need separate review. -An upstream fix reported by `--fix-available` does not guarantee that Homebrew already provides it. +Keep [shared team Brewfiles](Homebrew-for-Teams.md) in version control, then use the [fleet deployment and maintenance jobs](Homebrew-Fleet-Management.md) for installation, self-service and staged updates. +For security work, follow [vulnerability scanning and verified remediation](Homebrew-Vulnerability-Management.md), including `--vulnerable` and `--minimum-version` selection. +Serialise jobs on each prefix and retain their output and exit status; a successful upgrade alone does not verify remediation. ## Casks, services and shared destinations @@ -210,25 +215,27 @@ In `brew.env`, specify the destination as an absolute path to that account's App A shared destination such as `/Applications` needs suitable permissions provisioned separately. For casks that must supply checksums, `HOMEBREW_CASK_OPTS=--require-sha` rejects casks without them. +Use `brew outdated --cask --greedy` to assess self-updating casks and those using `version :latest`. +The Homebrew installation record can differ from an application's running version after it updates itself. + Caches, logs, configuration and user services belong to the managing account. A dedicated account's user service is not another user's service; plan its login requirements and lifecycle separately from package installation. Use the [`brew services` reference](Manpage.md#services-subcommand) when choosing user services or system services. ## Network configuration and reporting -For managed download infrastructure, see `HOMEBREW_API_DOMAIN`, `HOMEBREW_BOTTLE_DOMAIN` and `HOMEBREW_ARTIFACT_DOMAIN` in the [environment reference](Manpage.md#environment). -API and bottle mirrors can fall back to upstream sources. -`HOMEBREW_ARTIFACT_DOMAIN_NO_FALLBACK=1`, together with `HOMEBREW_ARTIFACT_DOMAIN`, makes artifact-mirror failures stop downloads instead of falling back. -Validate your mirror's coverage and keep its metadata current. -Use `HOMEBREW_NO_ANALYTICS=1` if your deployment should disable Homebrew analytics. +Follow the [mirror and network guidance](Homebrew-Package-Policies.md#use-mirrors-without-weakening-verification) and [private-tap authentication steps](Homebrew-Fleet-Management.md#publish-internal-tools-through-private-taps) when preparing unattended jobs. +Use the [inventory and SBOM guide](Homebrew-Inventory-and-SBOM.md) for reports and audit evidence, and your MDM's [administrator roles](Homebrew-Fleet-Management.md#reporting-and-administrator-access) for access control. +For build failures, retain diagnostics from the managing account's `~/Library/Logs/Homebrew` directory. -Collect inventory as the managing account: +## Apply operating-system execution rules -```sh -/opt/homebrew/bin/brew as-brew-user info --json=v2 --installed -/opt/homebrew/bin/brew as-brew-user config -/opt/homebrew/bin/brew as-brew-user doctor -``` +Homebrew package restrictions govern Homebrew operations; they do not prevent execution of a binary downloaded by another tool. +If you enforce execution rules through your MDM, account for Homebrew's shell scripts, portable Ruby, build tools and the software being installed. +Allowing an interpreter does not by itself restrict the scripts it can execute. -Use JSON output for inventory integrations and [Querying `brew`](Querying-Brew.md) for examples. -Keep failure output and consult the managing account's `~/Library/Logs/Homebrew` directory when investigating build failures. +On supported supervised Macs, Apple's [`com.apple.configuration.app.settings` declaration](https://github.com/apple/device-management/blob/release/declarative/declarations/configurations/app.settings.yaml) provides `AllowedBinaries` and `DeniedBinaries` from macOS 27. +Confirm support in your MDM before using it. +Apple requires a code directory hash or Team ID for an allowed binary; a path prefix alone is insufficient. +Inspect the actual installed executable with `codesign -dvvv /path/to/binary`, then maintain the rule as software changes. +Do not assume all Homebrew packages share a signing identity, and do not broadly trust a user-writable prefix as a substitute for reviewing executable code. diff --git a/docs/Homebrew-for-Teams.md b/docs/Homebrew-for-Teams.md new file mode 100644 index 0000000000000..1a6df4f47cb17 --- /dev/null +++ b/docs/Homebrew-for-Teams.md @@ -0,0 +1,136 @@ +--- +description: Manage Homebrew at work with a shared team Brewfile in Git. Set up colleagues, review package changes and coordinate updates on macOS and Linux without an MDM. +last_review_date: "2026-10-25" +--- + +# Homebrew for Teams: Manage a Shared Brewfile + +A shared Brewfile gives a team one reviewed list of tools and repeatable setup instructions for using Homebrew at work. +Keep it in Git, review changes through pull requests and have colleagues apply the agreed configuration to their own machines. +This workflow uses Homebrew and your existing Git host; it needs no MDM or central management service. + +Each colleague needs [Homebrew](Installation.md) and Git, and runs the commands as the owner of their own Homebrew installation. +The examples use formulae available on macOS and Linux. +The team shares a manifest, not a Homebrew installation or account. + +## Create the shared `Brewfile` + +1. Choose a repository everyone on the team can read. + Keep common tools in a small repository such as `team-tools`, and project-specific dependencies in each project's own Brewfile. + Choose who can approve changes and merge pull requests. +2. Save the agreed tools in a file named `Brewfile` at the repository root: + +```ruby +brew "git" +brew "jq" +brew "shellcheck" +``` + +3. Test it using the installation commands below, then commit and publish it through your usual Git review process. + Include those setup commands in the repository's README so new colleagues can find them. + +To start from an existing machine, use [`brew bundle dump`](Brew-Bundle-and-Brewfile.md#brew-bundle-dump), then remove personal and unrelated entries before committing. +See [supported Brewfile entries](Brew-Bundle-and-Brewfile.md#types) for applications and other package sources; check their platform requirements before adding them to a mixed-platform team's file. + +## Set up a colleague's machine + +1. Clone the repository and enter its directory, replacing this example URL with your team's repository: + + ```sh + git clone https://github.com/example/team-tools.git + cd team-tools + ``` + +2. Install missing tools and check that the Brewfile's requirements are satisfied: + + ```sh + brew bundle install --no-upgrade --file=Brewfile + brew bundle check --no-upgrade --file=Brewfile + ``` + + `--no-upgrade` skips routine upgrades of entries already installed; installing missing tools can still require dependency changes. + Add `--verbose` to a failed check to see unmet requirements. +3. Run the project's normal build or tests to verify the tools work together. + A successful Bundle check verifies package requirements, not application compatibility. + +## Give projects familiar setup commands + +Follow GitHub's [Scripts To Rule Them All](https://github.com/github/scripts-to-rule-them-all) convention so colleagues can use the same command names across projects. +Keep each wrapper small and let Homebrew manage the packages declared in that repository's Brewfile. + +1. Create a `script` directory and save this as `script/bootstrap`: + + ```bash + #!/bin/bash + set -euo pipefail + + cd "$(dirname "$0")/.." + brew bundle check --no-upgrade --file=Brewfile || + brew bundle install --no-upgrade --file=Brewfile + ``` + +2. Make it executable, run it and commit it alongside the Brewfile: + + ```sh + chmod +x script/bootstrap + script/bootstrap + ``` + +3. Document `script/bootstrap` as the dependency setup command. + Add `script/setup` for initial application state, `script/update` for changes needed after pulling and `script/test` for project tests where needed. + Setup and update scripts can call `script/bootstrap`; CI can use the same scripts once Homebrew is installed. + +Keep machine provisioning separate from project setup, and make bootstrap safe to repeat without resetting databases or overwriting personal configuration. +Leave command output and failures visible so colleagues can identify the failed step and retry after resolving the cause. +Keep package upgrades an explicit [team update](#coordinate-package-updates), separate from installing missing dependencies. + +## Review and share changes + +1. Create a branch in the repository and edit the Brewfile, or use [`brew bundle add`](Brew-Bundle-and-Brewfile.md#brew-bundle-add-and-brew-bundle-remove): + + ```sh + git switch -c add-ripgrep + brew bundle add --file=Brewfile ripgrep + git diff -- Brewfile + ``` + +2. Apply the [installation and check steps](#set-up-a-colleagues-machine), then test the affected projects on the supported platforms. +3. Commit the change and open a pull request explaining why the team needs it. + Brewfiles execute Ruby, so review changes as code and keep credentials out of them. +4. After merging, tell colleagues to update their checkout on the repository's default branch and apply the shared file: + + ```sh + git pull --ff-only + brew bundle install --no-upgrade --file=Brewfile + brew bundle check --no-upgrade --file=Brewfile + ``` + +Merging a pull request does not change anyone's installed packages until they run the commands. +Agree when the team should pull and apply changes, for example when starting a project or after a dependency change is announced. + +## Coordinate package updates + +1. Choose a colleague or CI environment to test updates before asking everyone to apply them. +2. Refresh Homebrew's metadata, then install the Brewfile without `--no-upgrade` to include available upgrades: + + ```sh + brew update + brew bundle install --file=Brewfile + brew bundle check --file=Brewfile + ``` + +3. Run project tests and share the result, including any migration or restart steps, before the rest of the team repeats the update. + Use [vulnerability scanning and remediation](Homebrew-Vulnerability-Management.md) when responding to security findings. + +A Brewfile records package choices, not locked versions: the same Git revision can install different versions on different days. +Reverting a Brewfile commit does not restore historical package versions or application data. +See [versioned formulae](Versions.md) when a project needs a supported major-version line. + +## Keep personal tools and remove retired entries + +Keep personal tools in a separate Brewfile or install them directly; colleagues can also apply project-specific Brewfiles alongside the team's file. +All of them affect the same local Homebrew installation, so removing an entry from one file does not uninstall it or establish that nobody still needs it. +Before using [`brew bundle cleanup`](Brew-Bundle-and-Brewfile.md#brew-bundle-cleanup), review the combined requirements of the team, projects and personal tools, and preview removals without `--force`. +Personal shell and editor settings can live in a separate dotfiles repository that team setup scripts leave untouched. + +If you later need centrally assigned installation jobs, reuse the reviewed Brewfile with the [MDM deployment guide](Homebrew-Fleet-Management.md#install-default-software-for-each-team). diff --git a/docs/How-to-Create-and-Maintain-a-Tap.md b/docs/How-to-Create-and-Maintain-a-Tap.md index 413047aebfa17..75f97535edabb 100644 --- a/docs/How-to-Create-and-Maintain-a-Tap.md +++ b/docs/How-to-Create-and-Maintain-a-Tap.md @@ -1,11 +1,14 @@ --- -last_review_date: "2026-06-19" +last_review_date: "2026-10-25" --- # How to Create and Maintain a Tap [Taps](Taps.md) are external sources of Homebrew formulae, casks and/or external commands. They can be created by anyone to provide their own formulae, casks and/or external commands to any Homebrew user. +For private repositories used by teams, see [internal software delivery and unattended credentials](Homebrew-Fleet-Management.md#publish-internal-tools-through-private-taps). +Apply [tap trust and package policies](Homebrew-Package-Policies.md) when deploying the tap across devices. + ## Creating a tap A tap is usually a Git repository available online, but you can use anything as long as it’s a protocol that Git understands, or even just a directory with files in it. If hosted on GitHub, we recommend that the repository’s name start with `homebrew-` so the short `brew tap` command can be used. See the [`brew` manual page](Manpage.md) for more information on repository naming. diff --git a/docs/Licence-Guidelines.md b/docs/Licence-Guidelines.md index 5a7ccaa53e735..e83e44209c34c 100644 --- a/docs/Licence-Guidelines.md +++ b/docs/Licence-Guidelines.md @@ -1,5 +1,5 @@ --- -last_review_date: "2026-07-18" +last_review_date: "2026-10-25" redirect_from: - /License-Guidelines --- @@ -8,6 +8,9 @@ redirect_from: Formulae in `homebrew/core` must use a licence compatible with the [Debian Free Software Guidelines](https://wiki.debian.org/DFSGLicenses) or be released into the public domain under the [DFSG public-domain guidance](https://wiki.debian.org/DFSGLicenses#Public_Domain). +These guidelines describe the licences of packaged software. +See [package licence policies](Homebrew-Package-Policies.md#choose-the-restriction-that-matches-the-requirement) for organisational restrictions. + ## Specifying a licence Each licence is identified using an identifier from the [SPDX License List](https://spdx.org/licenses/). diff --git a/docs/Manpage.md b/docs/Manpage.md index 30f61ec4ddf7d..6fc310aefac47 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -4440,6 +4440,12 @@ prefix-specific files take precedence over system-wide files (unless Note that these files do not support shell variable expansion (e.g. `$HOME`) or command execution (e.g. `$(cat file)`). +For MDM configuration, package restrictions and policy ownership, see: + +[Homebrew for Mac Admins][1] + +[Homebrew Package Policies][2] + `HOMEBREW_API_AUTO_UPDATE_SECS` : Check Homebrew's API for new formulae or cask data every @@ -5208,6 +5214,8 @@ Homebrew Documentation: Homebrew API: +[Homebrew for teams at work][3] + `git`(1), `git-log`(1) ## AUTHORS @@ -5239,3 +5247,8 @@ See our issues on GitHub: : + + +[1]: https://docs.brew.sh/Homebrew-for-Mac-Admins +[2]: https://docs.brew.sh/Homebrew-Package-Policies +[3]: https://docs.brew.sh/Homebrew-for-Teams diff --git a/docs/Querying-Brew.md b/docs/Querying-Brew.md index a7d63fc4a8ae9..289c6e9f57d6b 100644 --- a/docs/Querying-Brew.md +++ b/docs/Querying-Brew.md @@ -1,5 +1,5 @@ --- -last_review_date: "2025-02-08" +last_review_date: "2026-10-25" --- # Querying `brew` @@ -22,9 +22,15 @@ The default schema version is `v1`, which returns info about formulae; specify ` The schema itself is not currently documented outside of the code in [`formula.rb`](https://github.com/Homebrew/brew/blob/2e6b6ab3a20da503ba2a22a37fdd6bd936d818ed/Library/Homebrew/formula.rb#L1922-L2017) that generates it. +## Fleet inventory and security reporting + +Use `brew info --json=v2 --installed` for formula and cask inventory, including each installed formula keg's `sbom` path (`null` when missing). +See the [inventory guide](Homebrew-Inventory-and-SBOM.md) for installed-version fields, CSV exports and SBOM collection. +Use `brew outdated --vulnerable --json=v2` for upgrade candidates and `brew vulns --json` for findings and coverage; see [vulnerability management](Homebrew-Vulnerability-Management.md). + ## Examples -_The top-level element of the JSON output is always an array, so the `map` operator is used to act on the data._ +_The following `v1` examples return an array, so the `map` operator is used to act on the data._ ### Pretty-print a single formula's info diff --git a/docs/Tap-Trust.md b/docs/Tap-Trust.md index fd0c7791313e8..89ed0c588e6ee 100644 --- a/docs/Tap-Trust.md +++ b/docs/Tap-Trust.md @@ -1,5 +1,5 @@ --- -last_review_date: "2026-07-18" +last_review_date: "2026-10-25" --- # Tap Trust @@ -13,6 +13,9 @@ Non-official taps require explicit trust by default [since Homebrew 6.0.0](https `brew doctor` warns about non-official taps for which neither the tap nor any individual item is trusted. Commands that need to load an untrusted tap or item will fail until the relevant trust is granted. +For centrally managed devices, combine trust decisions with [package policies and approvals](Homebrew-Package-Policies.md#separate-tap-trust-from-package-approval). +Use [inventory and scan coverage](Homebrew-Vulnerability-Management.md#capture-findings-without-losing-errors) to identify installations omitted because their taps are untrusted. + ## Why tap trust exists Formulae, casks and external commands are executable package definitions, not plain metadata. diff --git a/docs/Taps.md b/docs/Taps.md index 24cdf47dd0fd5..d83cb7fb4106f 100644 --- a/docs/Taps.md +++ b/docs/Taps.md @@ -1,5 +1,5 @@ --- -last_review_date: "2026-07-18" +last_review_date: "2026-10-25" --- # Taps (Third-Party Repositories) @@ -10,6 +10,8 @@ The one-argument form assumes a repository on GitHub, while the two-argument for Code in a tap can run with your user's privileges. Read [Tap Trust](Tap-Trust.md) before using a non-official tap. +For distributing internal software at work, see [private taps in a managed fleet](Homebrew-Fleet-Management.md#publish-internal-tools-through-private-taps) and [package source policies](Homebrew-Package-Policies.md#separate-tap-trust-from-package-approval). + ## The `brew tap` command `brew tap` without arguments lists the currently tapped repositories. diff --git a/docs/Versions.md b/docs/Versions.md index fbfc4a7524917..3aadff7b14249 100644 --- a/docs/Versions.md +++ b/docs/Versions.md @@ -1,5 +1,5 @@ --- -last_review_date: "2026-04-05" +last_review_date: "2026-10-25" --- # Formulae Versions @@ -34,6 +34,9 @@ Versioned formulae we include in [homebrew/core](https://github.com/homebrew/hom Homebrew's versions should not be used to "pin" formulae to your personal requirements. If a versioned formula already exists in `homebrew/core`, prefer that first: it remains supported and updated by Homebrew. +For fleet policy thresholds, use `brew outdated --minimum-version` and `brew upgrade --minimum-version`; for vulnerability-based selection, use `--vulnerable`. +See [patch management](Homebrew-Vulnerability-Management.md#apply-and-verify-updates) for previews, pins and verification. + If you want something else, choose the smallest tool that fits: ### `brew pin` diff --git a/docs/index.md b/docs/index.md index e38fb1805a71c..d3972a2600bab 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,5 @@ --- -last_review_date: "2026-09-21" +last_review_date: "2026-10-25" --- Start with [installation](Installation.md), @@ -7,14 +7,13 @@ Start with [installation](Installation.md), [troubleshooting](Troubleshooting.md) and [FAQ (Frequently Asked Questions)](FAQ.md) guides if you are new to Homebrew. -Documentation is grouped below by audience: users, contributors, maintainers and those interested in Homebrew's governance. +Documentation is grouped below by audience: users, system administrators, contributors, maintainers and those interested in Homebrew's governance. ## Users - [`brew` manual page (command documentation, also available with `man brew`)](Manpage.md) - [Homebrew Blog (news on major updates)](https://brew.sh/blog/) - [Installation](Installation.md) -- [Homebrew for Mac Admins: MDM and Non-Admin Accounts](Homebrew-for-Mac-Admins.md) - [Support Tiers](Support-Tiers.md) - [Troubleshooting](Troubleshooting.md) - [FAQ (Frequently Asked Questions)](FAQ.md) @@ -44,6 +43,25 @@ Documentation is grouped below by audience: users, contributors, maintainers and - [Updating Software in Homebrew](Updating-Software-in-Homebrew.md) - [Adding Software to Homebrew](Adding-Software-to-Homebrew.md) +## Teams + +- [Homebrew for teams at work: shared Brewfiles](Homebrew-for-Teams.md) + +## System administrators + +- [Homebrew Software Inventory, SBOMs and Audit Reporting](Homebrew-Inventory-and-SBOM.md) +- [Homebrew Vulnerability Scanning and Patch Management](Homebrew-Vulnerability-Management.md) +- [Homebrew Package Policies and Supply Chain Protection](Homebrew-Package-Policies.md) + +## Mac Admins + +- [Homebrew for Mac Admins: MDM and Non-Admin Accounts](Homebrew-for-Mac-Admins.md) +- [Homebrew Fleet Management with MDM and Brewfiles](Homebrew-Fleet-Management.md) +- [Jamf Pro](Homebrew-and-Jamf-Pro.md) +- [Iru (formerly Kandji)](Homebrew-and-Iru.md) +- [Microsoft Intune](Homebrew-and-Microsoft-Intune.md) +- [Other MDMs](Homebrew-Fleet-Management.md#other-management-systems) + ## Contributors - [How to Open a Homebrew Pull Request (and get it merged)](How-To-Open-a-Homebrew-Pull-Request.md) diff --git a/docs/vale-styles/Homebrew/Headings.yml b/docs/vale-styles/Homebrew/Headings.yml index 213ade5e8293f..dbe7b0955e760 100644 --- a/docs/vale-styles/Homebrew/Headings.yml +++ b/docs/vale-styles/Homebrew/Headings.yml @@ -45,6 +45,7 @@ exceptions: - Linux - LLM - Launchpad + - MDM - MPI - Ops Team - PLC @@ -60,6 +61,7 @@ exceptions: - Security Team - SOS - Sublime Text + - Mac Admins - SourceForge - Subversion - URL diff --git a/docs/vale-styles/Homebrew/Titles.yml b/docs/vale-styles/Homebrew/Titles.yml index 0da705df845fb..842ed24009700 100644 --- a/docs/vale-styles/Homebrew/Titles.yml +++ b/docs/vale-styles/Homebrew/Titles.yml @@ -11,3 +11,4 @@ exceptions: - Homebrew/homebrew-core - Homebrew/homebrew-cask - (or Linux) + - (formerly Kandji) diff --git a/manpages/brew.1 b/manpages/brew.1 index 6ab77b31bbbc4..6847dcc8ccfa7 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -2814,6 +2814,16 @@ Note that environment variables must have a value set to be detected\. For examp User\-specific environment files take precedence over prefix\-specific files and prefix\-specific files take precedence over system\-wide files (unless \fB$HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY\fP is set, see below)\. .P Note that these files do not support shell variable expansion (e\.g\. \fB$HOME\fP) or command execution (e\.g\. \fB$(cat file)\fP)\. +.P +For MDM configuration, package restrictions and policy ownership, see: +.P +.UR https://docs\.brew\.sh/Homebrew\-for\-Mac\-Admins +Homebrew for Mac Admins +.UE +.P +.UR https://docs\.brew\.sh/Homebrew\-Package\-Policies +Homebrew Package Policies +.UE .TP \fBHOMEBREW_API_AUTO_UPDATE_SECS\fP Check Homebrew\[u2019]s API for new formulae or cask data every \fB$HOMEBREW_API_AUTO_UPDATE_SECS\fP seconds\. Alternatively, disable API auto\-update checks entirely with \fB$HOMEBREW_NO_AUTO_UPDATE\fP\&\. @@ -3362,6 +3372,10 @@ Homebrew API: .UR https://docs\.brew\.sh/rubydoc/ .UE .P +.UR https://docs\.brew\.sh/Homebrew\-for\-Teams +Homebrew for teams at work +.UE +.P \fBgit\fP(1), \fBgit\-log\fP(1) .SH "AUTHORS" Homebrew\[u2019]s Project Leader is Mike McQuaid\.