Skip to content

install.sh: TOCTOU between tag resolution and tarball download; no integrity check #1726

Description

@rpriven

install.sh resolves the latest tag via a redirect probe (with API and stamped-tag fallbacks), then separately downloads archive/refs/tags/${TAG}.tar.gz and pipes it straight to tar. Two hygiene gaps for a security-minded audience:

  1. TOCTOU: resolve-then-fetch means the tag can move (or the release be replaced) between the two requests. Pinning the download to the resolved commit SHA closes it.
  2. No checksum: nothing verifies the tarball. Publishing per-release hashes (even just in the release notes) and checking before extraction would let cautious users verify what they're about to place into their harness config root.

Low severity in practice, cheap to fix, and it matches the trust posture the rest of the release pipeline (the new sanitizer/font/pointer gates) is clearly aiming at. For what it's worth I verified my install out-of-band by diffing the served install.sh and INSTALL.md against the tagged tree before running anything — identical — but users shouldn't need to do that by hand.

Environment: Debian 13 (headless), Claude Code 2.1.220, bun 1.3.14, fresh OS user, installed via https://ourlifeos.ai/install at tag v7.28.3 (36c6f01). All line references are to this tag. One of four reports from the same fresh-install trial.

— Reported by Rob Pratt (@rpriven), co-authored with Kai.

Activity

  1. danielmiessler commented on Aug 7, 2026

    @danielmiessler
    Owner

    Fixed in source: the installer now resolves the tag to a commit SHA and downloads the pinned archive (closing the TOCTOU), downloads to a temp file instead of piping to tar, prints the tarball's sha256 before extraction, and hard-fails on mismatch when LIFEOS_EXPECTED_SHA256 is set (including refusing to install unverified when no hash tool exists). The stale fallback tag went in the same pass. Rides the next release. Thanks — and to your Kai for the out-of-band diff verification; that's the right instinct.

  2. ariadev79 commented on Oct 11, 2026

    @ariadev79

    Hey, I’m new here and looking forward to using LifeOS!

    Following up on this, thanks for the commit pinning and hash check. One small piece is still open: install.sh can hard-fail on a mismatch when LIFEOS_EXPECTED_SHA256 is set, but releases don’t publish a hash, so most users have nothing to set it to. As a minor hygiene improvement, could each release publish its SHA-256? Attaching the tarball as a release asset would do it, since GitHub records asset digests automatically and those bytes stay stable. A later step could have the installer verify it by default. It feels worth it since setup installs hooks that run in every Claude Code session. Happy to help with a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions