Skip to content
/ sfetch Public

Secure, verifiable, zero-trust downloader for the uncertain world

License

Notifications You must be signed in to change notification settings

3leaps/sfetch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

125 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sfetch

Go 1.23+ License: Apache 2.0 Release

Secure, verifiable, zero-trust downloader for the uncertain world

The one-liner

sfetch is the curl | sh you can actually trust in 2026.

A tiny (~3 MB), statically-linked Go binary that downloads release artifacts from GitHub and verifies signatures and checksums automatically - using minisign, PGP, or raw ed25519.

No runtime dependencies. No package manager required. Works in CI, Docker, and air-gapped environments. See CI/CD Usage Guide for container and pipeline examples.

Why sfetch exists

Every modern engineering org signs their releases now.
Yet we still ship 15-line bash bootstrap scripts that do manual curl → sha256sum → maybe cosign verify.

sfetch is the missing 1% that deletes those scripts forever.

Pair with shellsentry

shellsentry analyzes shell scripts for risky patterns before you run them. Use sfetch to acquire scripts safely, then shellsentry to inspect what's inside:

# Install both tools (verified with minisign signatures)
sfetch --repo 3leaps/sfetch --latest --dest-dir ~/.local/bin
sfetch --repo 3leaps/shellsentry --latest --dest-dir ~/.local/bin

The new curl | sh - verified download, inspected before execution:

# Fetch with sfetch (trust-scored), analyze with shellsentry, execute if safe
sfetch --url https://example.com/install.sh --follow-redirects --output install.sh
shellsentry --exit-on-danger install.sh && bash install.sh

Or the complete zero-trust pipeline:

# GitHub release URL → auto-upgrade to verified release → analyze → execute
sfetch https://github.com/helm/helm/releases/download/v3.14.0/get_helm.sh --output get_helm.sh
shellsentry --exit-on-danger get_helm.sh && bash get_helm.sh

Why this matters: sfetch tells you if you can trust the source; shellsentry tells you if you can trust the content.

Security & Verification

See docs/security.md.

Asset Discovery

Auto-selects via heuristics (docs/pattern-matching.md) and classifies assets (archives vs raw scripts/binaries vs package-like). Raw files skip extraction; scripts/binaries are chmod'd on macOS/Linux. Use --asset-match for glob/substring selection or --asset-regex for advanced regex.

Raw GitHub content

Fetch files directly from GitHub repos - no releases required. Useful for install scripts, config files, or any repo-hosted content.

# Fetch install script from main branch
sfetch --github-raw Homebrew/install@HEAD:install.sh --dest-dir /tmp

# Pin to a specific version/ref
sfetch --github-raw nvm-sh/nvm@v0.40.1:install.sh --output nvm-install.sh

# Paste a raw.githubusercontent.com URL - sfetch detects and handles it
sfetch --url https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh

Trust level: 25/100 (HTTPS transport only - no signature verification available for raw repo content).

Arbitrary URLs

Fetch any URL with built-in safety defaults. HTTPS is mandatory; redirects are blocked; you control every relaxation.

# Fetch an installer script (follows redirects for CDN-hosted content)
sfetch --url https://get.docker.com --follow-redirects --output get-docker.sh

# Fetch and see trust assessment without downloading
sfetch --url https://sh.rustup.rs --dry-run

Smart URL routing: Paste a GitHub release URL and sfetch automatically upgrades to the full verification flow:

# This URL...
sfetch https://github.com/junegunn/fzf/releases/download/v0.56.3/fzf-0.56.3-darwin_arm64.tar.gz

# ...auto-upgrades to: --repo junegunn/fzf --tag v0.56.3 --asset-match "fzf-*darwin_arm64*"
# Trust jumps from 25/100 (bare URL) to 45/100 (checksum verified)

Security defaults - you can't accidentally do something unsafe:

Default Override Why
HTTPS only --allow-http Can't accidentally download over plaintext
Redirects blocked --follow-redirects Can't be silently redirected to a malicious host
Credentials rejected (none) Can't leak auth tokens in URLs during redirects

Additional flags: --max-redirects (default 5), --allowed-content-types, --allow-unknown-content-type.

Install permissions

  • Archives (.tar.gz, .zip, etc.): Permissions from the archive are preserved. Executables packaged with 0755 remain executable after extraction.
  • Raw scripts/binaries (e.g., install.sh, kubectl): Automatically set to 0755 on macOS/Linux to ensure executability.
  • Cross-device installs: When --dest-dir is on a different filesystem than the temp directory (common in containers), sfetch falls back to copy and preserves the source permissions.

Proxy support

sfetch honors standard proxy environment variables and provides CLI flags for explicit control.

Environment variables (case-insensitive, zero-config):

  • HTTP_PROXY, HTTPS_PROXY, NO_PROXY

CLI flags (override env when present):

  • --http-proxy <url>, --https-proxy <url>, --no-proxy <csv>
# Via environment (common in CI/enterprise)
export HTTPS_PROXY=http://proxy.corp.example:8080
sfetch --repo 3leaps/sfetch --latest --dest-dir ~/.local/bin

# Via flags (explicit override)
sfetch --repo 3leaps/sfetch --latest --https-proxy http://localhost:8888 --dest-dir /tmp

Signature verification

Minisign - pure-Go, no external dependencies

  • --minisign-key <pubkey.pub> - path to public key file
  • --minisign-key-url <url> - download key from URL
  • --minisign-key-asset <name> - fetch key from release assets
  • --require-minisign - fail if minisign verification unavailable
  • Auto-detects *.pub files from release assets when no key flags provided

PGP - requires gpg binary

  • --pgp-key-file <key.asc> - path to ASCII-armored public key
  • --pgp-key-url <url> - download key from URL
  • --pgp-key-asset <name> - fetch key from release assets
  • Auto-detects *-signing-key.asc or *-release*.asc from release assets

Raw ed25519 - pure-Go (uncommon format)

  • --key <64-hex-bytes> for .sig or .sig.ed25519 files

See docs/key-handling.md for details. Run sfetch -helpextended for examples.

Verification assessment

sfetch computes a trust score (0–100) from the verification plan/results, and can optionally gate installs with --trust-minimum.

Design guide: docs/trust-rating-system.md.

Dry-run mode - see what verification is available before downloading:

sfetch --repo BurntSushi/ripgrep --latest --dry-run

Enforce a minimum trust score (useful in CI):

# Require at least medium trust
sfetch --repo 3leaps/sfetch --latest --trust-minimum 60 --dest-dir /tmp

Provenance records - structured JSON for audit trails and CI:

sfetch --repo 3leaps/sfetch --latest --dest-dir /tmp --provenance-file audit.json

Verify installed binary - print instructions to verify your sfetch installation:

sfetch --self-verify

Self-update - update sfetch to the latest verified release:

# Update if newer version is available (skips reinstall if already current)
sfetch --self-update --yes

# Force reinstall even if already at the target version
sfetch --self-update --self-update-force --yes

# Pin to a specific version (allows downgrades)
sfetch --self-update --tag v0.2.3 --yes

For machine-readable trust anchors:

sfetch --show-trust-anchors        # plain: minisign:<key>
sfetch --show-trust-anchors --json # JSON with pubkey and keyId

See docs/examples.md for comprehensive real-world examples.

Build, versioning & install

sfetch uses Semantic Versioning. See ADR-0001 for versioning history.

make build             # produces bin/sfetch_${GOOS}_${GOARCH}
make install           # installs to ~/.local/bin by default
INSTALL_BINDIR=~/bin make install  # override install location
  • Edit buildconfig.mk to change the canonical binary name (NAME) or default install destination once.
  • On Windows, make install targets %USERPROFILE%\bin; ensure that directory is present in PATH.

Bootstrap install

# Using curl
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/install-sfetch.sh | bash

# Using wget
wget -qO- https://github.com/3leaps/sfetch/releases/latest/download/install-sfetch.sh | bash

Installer options

Pass arguments using bash -s --:

# Install to custom directory
curl -sSfL .../install-sfetch.sh | bash -s -- --dir ~/bin

# Install specific version
curl -sSfL .../install-sfetch.sh | bash -s -- --tag v0.2.0

# Dry run (download and verify, don't install)
curl -sSfL .../install-sfetch.sh | bash -s -- --dry-run

# Skip confirmation prompt
curl -sSfL .../install-sfetch.sh | bash -s -- --yes

# Allow checksum-only (NOT recommended; skips signature verification)
curl -sSfL .../install-sfetch.sh | bash -s -- --allow-checksum-only

The installer:

  • Detects platform (linux/darwin/windows, amd64/arm64)
  • Requires minisign verification by default using the embedded trust anchor
  • Optional GPG fallback with pinned fingerprint; checksum-only requires explicit --allow-checksum-only

Verify before piping to bash

For users who prefer to verify the installer before execution:

# Detect OS-appropriate SHA256 command (macOS uses shasum, Linux uses sha256sum)
if command -v sha256sum &>/dev/null; then
  SHA_CMD="sha256sum"
else
  SHA_CMD="shasum -a 256"
fi

# Download assets (curl)
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/install-sfetch.sh -o install-sfetch.sh
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/SHA256SUMS -o SHA256SUMS

# Download assets (wget alternative - use -O to overwrite existing files)
# wget -qO install-sfetch.sh https://github.com/3leaps/sfetch/releases/latest/download/install-sfetch.sh
# wget -qO SHA256SUMS https://github.com/3leaps/sfetch/releases/latest/download/SHA256SUMS

# Option A: Verify with minisign (recommended)
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/SHA256SUMS.minisig -o SHA256SUMS.minisig
minisign -Vm SHA256SUMS -P RWTAoUJ007VE3h8tbHlBCyk2+y0nn7kyA4QP34LTzdtk8M6A2sryQtZC
$SHA_CMD -c SHA256SUMS --ignore-missing

# Option B: Verify with GPG (uses temp keyring)
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/SHA256SUMS.asc -o SHA256SUMS.asc
curl -sSfL https://github.com/3leaps/sfetch/releases/latest/download/sfetch-release-signing-key.asc -o sfetch-release-signing-key.asc
GPG_TMPDIR=$(mktemp -d)
gpg --homedir "$GPG_TMPDIR" --import sfetch-release-signing-key.asc
gpg --homedir "$GPG_TMPDIR" --verify SHA256SUMS.asc SHA256SUMS
rm -rf "$GPG_TMPDIR"
$SHA_CMD -c SHA256SUMS --ignore-missing

# Run after verification
bash install-sfetch.sh

Manual signing workflow

CI uploads unsigned archives. Maintainers generate SHA256SUMS and SHA512SUMS locally, then sign them with minisign (primary) and optionally PGP:

export MINISIGN_KEY=/path/to/sfetch.key
export PGP_KEY_ID=security@fulmenhq.dev  # optional

RELEASE_TAG=v0.2.0 make release-download
RELEASE_TAG=v0.2.0 make release-checksums
RELEASE_TAG=v0.2.0 make release-sign
make release-export-minisign-key
make release-export-key                   # if using PGP
RELEASE_TAG=v0.2.0 make release-notes
RELEASE_TAG=v0.2.0 make release-upload

Set RELEASE_TAG to the tag you're publishing. The scripts in scripts/ can be used individually if you prefer manual control.

Quick examples

# Download with auto-detected verification (minisign or PGP key from release assets)
sfetch --repo 3leaps/sfetch --latest --dest-dir ~/.local/bin

# Download installer script (no extraction, auto-chmod)
sfetch --repo 3leaps/sfetch --latest --asset-match "install-sfetch.sh" --dest-dir /tmp

# Standalone binary with explicit override for ambiguous extensions
sfetch --repo owner/tool --latest --asset-type raw --dest-dir /usr/local/bin

# Match by glob/substring instead of regex
sfetch --repo jedisct1/minisign --latest --asset-match "*macos*.zip" --dest-dir /usr/local/bin

# Advanced: regex match remains available
sfetch --repo jedisct1/minisign --latest --asset-regex "minisign-.*-macos.zip$" --dest-dir /usr/local/bin

# Dry-run to assess what verification is available
sfetch --repo BurntSushi/ripgrep --latest --dry-run

# Explicit minisign key
sfetch --repo jedisct1/minisign --latest --minisign-key /path/to/key.pub --dest-dir /usr/local/bin

# PGP verification
sfetch --repo fulmenhq/goneat --latest --pgp-key-file fulmen-release.asc --dest-dir /usr/local/bin

# Pin to specific version
sfetch --repo fulmenhq/goneat --tag v0.3.14 --dest-dir /usr/local/bin

Migrating from curl/wget

Replace risky one-liners with trust-scored, verifiable downloads:

Old pattern sfetch equivalent
curl -fsSL https://get.docker.com | sh sfetch --url https://get.docker.com --follow-redirects -o get-docker.sh && sh get-docker.sh
wget https://github.com/.../v1.0/tool.tar.gz sfetch https://github.com/.../v1.0/tool.tar.gz (auto-upgrades to release verification)
curl -x proxy:8080 ... sfetch --https-proxy http://proxy:8080 ...

Key differences from curl/wget:

  • Never pipes directly to shell - download first, execute separately
  • Every download gets a trust score (0-100)
  • GitHub URLs auto-upgrade to release verification when possible
  • Redirects require explicit opt-in (--follow-redirects)

About

Secure, verifiable, zero-trust downloader for the uncertain world

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •