Report suspected vulnerabilities privately through GitHub's private vulnerability reporting for this repository, or by email to repo@pigsty.cc. Please do not open a public issue for an unfixed vulnerability.
Include the Farrow version (farrow --json version), the host platform, and the
smallest reproduction you have. You should get an acknowledgement within five
working days.
Farrow is pre-1.0. Fixes land in the next tagged release; there is no separate backport line yet.
Farrow runs unprivileged. It asks for administrator access for exactly two host transactions, each announced before it happens:
- Installing the host-global fixed-IP network.
farrow network installprints the complete privileged plan and applies nothing without--yes.farrow network uninstallreverses it, restoring the recorded original ownership and mode of anything it changed. - Installing the hosts helper.
farrow-hosts-helperis a separate, minimal, root-owned binary at/opt/farrow/libexec/farrow-hosts-helper. It is the only component that ever writes the system hosts file.
Everything else — image cache, deployment state, SSH material, QEMU processes —
is owned by the invoking user under $FARROW_HOME and never needs root.
The helper is deliberately hard to misuse. It rejects any invocation that does not satisfy every one of these:
- a target that is exactly the platform's native hosts path, and a staging path that is absolute;
- an effective UID of 0, with a target owned by
root:root, unwritable by group and other, and with a link count of exactly one; - a staging file with mode
0600, a link count of one, and ownership matchingSUDO_UID; - a before-digest that still matches the target and an after-digest that matches the staging file, so a plan reviewed against a since-changed hosts file is refused rather than applied;
- a post-write re-read whose digest, ownership, link count, and mode all match what was promised.
The CLI only ever invokes a helper whose SHA-256 matches the digest compiled into that exact Farrow build, so a mismatched or substituted helper is not run.
- Release archives, Linux packages, SPDX SBOMs, the Homebrew formula, the
installer, and the release metadata are all listed in
checksums.txt. checksums.txtis signed with keyless Sigstore (checksums.txt.sigstore.json), and its SLSA provenance is attested (checksums.provenance.sigstore.json). The release workflow verifies both against its own GitHub Actions OIDC identity before publishing.- Builds are reproducible:
-trimpath,-buildid=, andSOURCE_DATE_EPOCHderived from the tagged commit. - The Go toolchain, GoReleaser, nFPM, Syft, Cosign, Staticcheck, and
govulncheck are all version-pinned in
packaging/toolchain.envand verified at release time.
The user-scoped installer always verifies the selected archive against
checksums.txt. When Cosign is installed it additionally requires and verifies
checksums.txt.sigstore.json; a missing or invalid bundle is fatal. The narrow
FARROW_INSTALL_ALLOW_UNSIGNED=1 escape hatch applies only to a missing bundle
for an explicitly trusted development/fork release. It never overrides a
signature-verification failure, and the installer prints an unmissable warning
plus an unsigned result label when used.
Verify a release before trusting it:
cosign verify-blob --bundle checksums.txt.sigstore.json \
--certificate-identity "https://github.com/pgsty/farrow/.github/workflows/release.yml@refs/tags/v<version>" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
checksums.txt
shasum -a 256 -c checksums.txt --ignore-missingGuest images are distribution-owned artifacts pinned by SHA-256 in a catalog
signed with the keys embedded in the binary. Every fetch verifies the digest,
the byte count, the qcow2 structure, and the virtual size before the image is
published into the cache. Farrow refuses catalog upstream URLs that point at a
moving path such as latest or current.
Farrow does not patch or harden guest images. They are upstream cloud images, and their contents are the upstream vendor's responsibility.