Skip to content

Security

Bryan Speelman edited this page Sep 3, 2026 · 1 revision

Security

What bothy verifies, what it deliberately does not, and where each wall ends. To report a hole, use SECURITY.md — privately, through GitHub's security advisories, not a public issue.

What bothy downloads, and what checks it

bothy fetches eight tools. Every one is pinned to a version and a sha256 in bothy.lock, and the checksum is verified before the file is kept. A tool already on your PATH at a good version is used as-is and nothing is downloaded.

The limit, stated plainly: those are other projects' releases. A checksum proves you got the bytes bothy expected — it does not prove those bytes are good. bothy does not sign what it did not build, and the pin records what the maintainer downloaded on the day they ran bothy lock.

What bothy itself is signed with

Nothing you have to trust a key for. Release artifacts are signed by the GitHub Actions workflow that built them, keyless, and recorded in a public transparency log — so the binary can be traced to a specific run of a specific workflow on a specific commit (ADR-030).

There is deliberately no private key: none to store, rotate, or leak.

What that does not do: it does not make a compromise impossible, it makes one visible and permanent. If this repository's Actions were compromised, the attestation would faithfully record the attacker's build — and that record could not be quietly withdrawn.

And it is not what Gatekeeper asks. Apple wants an identifiable paying developer account; the attestation answers a different question. Both are real, neither substitutes for the other. See Installing.

curl | sh

The install script is fetched over HTTPS and run, unsigned, before bothy exists to verify anything. This is a real gap and it is not solved — no signature on an artifact fixes verifying the verifier.

What you can do instead: download it, read it, then run it. It is one file and deliberately small.

curl -fsSL -o install.sh https://raw.githubusercontent.com/bspeelm/bothy/main/bootstrap/install.sh
less install.sh
sh install.sh

Or skip it: go install, the .deb, or dnf all avoid the question.

The wall around the agent

bothy confine runs the agent in a rootless podman container with your project directory and the agent's own credentials mounted, and nothing else from $HOME. It is opt-in and there is no setting that turns it on.

What it stops: every other project, ~/.ssh, ~/.aws, your shell history. Verified rather than assumed — a test fails if the invocation ever mounts $HOME.

What it does not stop, on purpose:

the network the agent calls its API; that is the job. This is a filesystem wall, not a network one
the agent's own credentials mounted, or it cannot log in and the wall protects nothing you wanted
the project directory mounted writable, because editing it is the point

Without confine, there is no wall at all — and bothy says so rather than implying otherwise. The agent runs as you, with your access, exactly as it would if you had started it yourself. bothy is not making that worse; it owns the launch, which is a position to make it better if you ask.

What bothy does not do

  • No telemetry, no auto-updater, no background service. A test fails if any shipping file names a host that is not GitHub.
  • It does not touch your dotfiles. Not ~/.vimrc, not ~/.config/yazi, not your git config. It writes into its own tree and points tools there for one process (ADR-009).
  • It never asks for root.

Scope for a report

In scope: the release pipeline, the confinement wall, bootstrap/install.sh, the Homebrew cask's quarantine removal, and the configs bothy generates for other tools. Out of scope: what the agent does, and holes in the tools bothy fetches — though a hole in how bothy pins or verifies them is very much in scope. The full statement is SECURITY.md.

Clone this wiki locally