Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,13 @@ Burrow drives a bundled, open-source Mole engine (an MIT fork of `mo`). The hone
recordings, user files, user paths, metrics, or stored IP; turn it off in
Settings. PostHog delivery and its bounded sanitized retry outbox run entirely
off AppKit's main thread. Full list in **[TELEMETRY.md](TELEMETRY.md)**.
- **No background root helper.** When Clean/Optimize need admin rights, macOS's
own dialog asks you and Burrow runs that one `mo` command, then exits — you
approve every elevation.
- **No background root helper by default.** When Clean/Optimize need admin
rights, macOS's own dialog asks you and Burrow runs that one `mo` command,
then exits — you approve every elevation. You can opt in to a small signed
helper so those prompts accept Touch ID; it grants no standing privilege
(every root operation still authenticates, every time), performs only scan,
clean, and optimize, and can be removed from Settings. Details in
**[SECURITY.md](SECURITY.md)**.
- **Local-only surfaces:** the MCP/HTTP surfaces bind to loopback only
(`127.0.0.1`) and history is stored locally. On Windows, the HTTP REST toggle
disables REST endpoints but keeps the local `/mcp` bridge route available for
Expand Down
105 changes: 52 additions & 53 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,56 @@
# Burrow 0.11.2
# Burrow 0.12.0

A system-metrics, updater, and launch-reliability patch. This release corrects
CPU sampling, stops expected Sparkle conditions from looking like product
defects, gives AppKit a settled launch turn before creating the menu-bar item,
and makes sampled app hangs reliably reach the issue tracker.
Burrow's admin operations can now authenticate with **Touch ID**.

> **Affected macOS 27 beta users:** please install 0.11.2 and report the result
> in [#319](https://github.com/caezium/Burrow/issues/319). The exact Beta 4
> compatibility guard remains in place, and the issue stays open until a
> notarized build is verified on a Mac that reproduced the freeze.
Until now every elevated action went through macOS's classic authorization
dialog, which is password-only by construction — it never offers Touch ID, and
it can't be cancelled safely. This release adds an optional signed helper that
replaces that path.

## Added
- **Touch ID for admin operations.** Install the helper in **Settings ▸
Advanced ▸ Privileged helper** and Clean, Optimize, the admin scan previews,
Flush DNS, Renew DHCP, and the Login Items list all authenticate through the
system's normal prompt — which offers Touch ID where the hardware has it, and
falls back to your password everywhere else.
- **The Login Items list is now complete.** Reading it needs root, so
previously macOS raised its own unexplained "sfltool wants to make changes"
prompt and still returned only a partial list. Through the helper it's one
prompt you recognise, and the full list.

## What the helper can and cannot do

It is strictly opt-in, takes its own one-time macOS approval, and grants no
standing access — you authenticate for each operation you start.

It accepts seven fixed operations and builds every command line itself. There
is no field in its API for a path, a shell string, or an executable, so it
cannot be asked to run anything else. It runs the engine sealed inside the
signed app plus four Apple tools by absolute path, each as a separate process
with no shell involved. Only Burrow can talk to it: callers are pinned to the
app's bundle identifier and signing team by the system.

One honest caveat: the credential from your authentication stays valid for ten
seconds, because it has to survive the hop from the app to the helper. A second
operation begun inside that window won't prompt again. Full detail in
[SECURITY.md](https://github.com/caezium/Burrow/blob/main/SECURITY.md).

Not installing it changes nothing — every operation keeps working exactly as it
does today, through the existing password prompt. You can remove the helper at
any time from Settings, or from System Settings ▸ General ▸ Login Items &
Extensions.

## Changed
- **Flush DNS no longer runs a root shell.** It previously elevated
`/bin/sh -c "dscacheutil -flushcache; killall -HUP mDNSResponder"`, handing a
command string to a shell running as root. It's now two separate processes
with fixed arguments.
- **Removed the "Touch ID for sudo" setting.** It configured `pam_tid` for
terminal `sudo` and never affected Burrow's own admin prompts, which is what
people expected it to do. Those prompts are what the privileged helper now
covers. Nothing already configured on your Mac is changed by removing it; to
undo it yourself, run `mo touchid disable`.

## Fixed
- **CPU usage now reflects a representative sampling interval.** The bundled
engine keeps a tick baseline across refreshes, samples before the other
collectors fan out, and derives total usage from summed tick deltas. This
removes the roughly doubled readings and coarse per-core fractions reported in
[#335](https://github.com/caezium/Burrow/issues/335). A cold one-shot status
command can take about 600 ms longer; ongoing GUI sampling reuses its existing
refresh interval and adds no wait. ([#340](https://github.com/caezium/Burrow/pull/340))
- **Updater failures now mean what they say.** Running from a disk image or a
translocated location, ordinary network failures, and user cancellation remain
measurable in PostHog without opening Sentry issues. Sparkle keeps ownership of
its native move-to-Applications and scheduled-retry UI. Configuration,
signature, installation, and unknown failures still create exactly one
scrubbed Sentry diagnostic per cycle. ([#339](https://github.com/caezium/Burrow/pull/339))
- **The normal menu-bar path no longer races the first AppKit launch turn.**
Burrow waits one second before creating its status item, then retains the
existing 30-second stability window. The safeguard for macOS 27 Beta 4 build
`26A5388g` remains exact-build-only; a later macOS build returns to the normal
guarded path automatically. ([#339](https://github.com/caezium/Burrow/pull/339))

## Improved
- **App-hang evidence can no longer disappear at the Sentry bridge.** Sampled
hangs are collected into bounded weekly GitHub digests instead of being
silently skipped. Cursor pagination reaches older unseen groups, full digests
roll into numbered parts, and deferred groups remain eligible for the next
run. ([#339](https://github.com/caezium/Burrow/pull/339))
- **Launch and updater health now have explicit lifecycle outcomes.** Fixed-name
scheduled, stabilizing, and stable milestones include bounded app release,
macOS build, launch phase, and status-item state, so future failures can be
separated without collecting free text or user data.

## Privacy
- **Telemetry remains optional, unlinked, and non-tracking.** One Settings
switch disables both PostHog analytics and Sentry diagnostics. Updater
diagnostics contain fixed categories and bounded error domains/codes—never
descriptions, URLs, response bodies, network names, paths, screen content, or
files. The privacy manifest remains unchanged and accurate.

## Security
- **Publishing still fails closed, including the external Homebrew tap.** Before
any release build begins, CI requires every signing, notarization, Sparkle,
and tap credential, then proves the tap token with a reversible Git
write. The tap credential is isolated from the engine checkout so a successful
notarized release cannot fail at the final cask push because the wrong token
was left in Git configuration.
- A failed elevated run could report "Done — caches cleared" when nothing had
actually run. Failures now say so.
56 changes: 51 additions & 5 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,60 @@ or notarization and changes between builds.

This is the part people rightly scrutinize in cleaners. Burrow's model:

- **Burrow installs no privileged/background helper and no XPC root
service.** There is nothing persistently running as root and nothing for
another local process to connect to.
- **By default Burrow installs no privileged helper.** Out of the box there
is nothing running as root and nothing for another local process to
connect to.
- When **Clean** or **Optimize** needs admin rights, **macOS's own
authorization dialog** asks for your password, and Burrow runs the
matching `mo` command for that single action, then exits. You see and
approve every elevation. (See `CommandRunner.runElevated` in
`macos/Sources/TaskReport.swift`.)
approve every elevation.
- **Optional privileged helper.** Settings ▸ Advanced can install a small
signed launch daemon (`SMAppService`) so those same operations can
authenticate with Touch ID instead of a password-only prompt. It is
strictly opt-in and takes its own one-time macOS approval. If you install
it:
- **It grants no standing privilege.** Installing the helper authorizes
nothing, and there is no "authenticate once for this launch". You are
asked to authenticate for each privileged operation you start.
- **The one caveat, stated honestly:** the credential from that
authentication stays valid for a 10-second window, because it has to
survive the hop from the app to the helper. A second operation begun
inside that window would not prompt again. The window covers an
inter-process message, not a user changing their mind, and it is the
shortest value that lets the check work at all. The rest is enforced by
the right's own definition (`shared: false` keeps the credential out of
other processes, `allow-root: false` stops the root helper satisfying it
by itself), and each operation ID is served at most once so a captured
request cannot be replayed.
- **It cannot be asked to run anything else.** The helper accepts seven typed
operations — scan, clean, optimize, the optimize preview, flush DNS,
renew DHCP, and reading the Login Items list — and derives every command
line itself. There is no field in its API for a path, a shell string, or
an executable, so a caller that fully controls the message still cannot
express "run this".
- **The only value a caller supplies** is the network interface name for
renew DHCP. It is checked twice: against a strict `en0`-shaped pattern,
and against the interfaces that actually exist on the machine. A
well-formed name for an interface that isn't there is refused.
- **No shell.** The helper runs the bundled engine, plus exactly four
system tools by absolute path (`/usr/bin/dscacheutil`, `/usr/bin/killall`,
`/usr/sbin/ipconfig`, `/usr/bin/sfltool`), each as a separate process with
fixed arguments.
This is stricter than the path it replaces: flushing DNS previously
elevated `/bin/sh -c "dscacheutil -flushcache; killall -HUP mDNSResponder"`,
handing a command string to a root shell.
- **Only Burrow can talk to it.** The daemon pins its callers to Burrow's
bundle identifier and signing team via the XPC connection's code-signing
requirement, so another local process cannot reach it or use it to raise
a credential prompt.
- **It runs only your engine, or those four Apple tools.** The engine it
executes is the copy inside the app bundle, resolved relative to the
helper's own path, never through `PATH` or an environment variable. Before
running anything the helper verifies the whole app bundle against its own
signing team, which seals the engine and every library the engine loads.
- **You can remove it** from Settings, or from System Settings ▸ General ▸
Login Items & Extensions.
- Code: `macos/Sources/PrivilegedHelper/`, `macos/HelperSources/`.
- **Honest caveat:** official builds elevate the engine sealed inside the
Developer ID signed app. A source build can fall back to an external `mo`;
if it does, that executable is only as trustworthy as its install location
Expand Down
Loading
Loading