Skip to content

SAM v3.1.1 — One Bar

Choose a tag to compare

@richhabits richhabits released this 02 Aug 06:54
· 552 commits to main since this release

A security fix. SAM held writing to a high bar and quietly let reading through.

Fixed

  • Your notes were readable by any other app on this Mac. /api/vault/log, /api/vault/graph
    and /api/vault/stats answered any request that reached the loopback port, with no credential
    at all. The guard on the privileged routes asks whether a request is a mutation — and a GET
    never is, so every read walked straight past it. What leaked is note titles, timestamps, the
    vault path and a graph built by walking the whole vault. Not credentials, and not remotely
    reachable — but any process on your machine could ask, including a supply-chained dependency
    inside some unrelated app, and it never had to know a secret.

    Reads of your private content are now held to the same bar as a change: the desktop app's
    per-launch passkey, or a session you approved by pairing. Every real client already carries
    one, so nothing you use loses access — the app sends the passkey, a paired browser its cookie,
    your phone the same token as a Bearer.

    If you run SAM only as the desktop app on a machine where you trust every other program, the
    practical exposure was small. Update anyway; the routes were open to anything.

  • The keepalive was not keeping anything alive. If you installed the launchd agent with
    scripts/install-server-daemon.sh, it pointed at a built server path that no longer existed,
    so every start died instantly and launchd tried again five seconds later — 60,104 failed
    starts and 28 MB of identical stack traces, while SAM appeared simply to be down. A dead
    keepalive is quiet, and a crash-looping one is quiet in the same way.

    launchd cannot make this call on its own: it cannot tell a crash apart from a start that
    should not have happened, and both normal reasons to hold off — the repo's drive not mounted,
    or the desktop app already serving the port with its own passkey — look exactly like a crash.
    A supervisor now makes that decision, waits quietly instead of looping, and stands down when
    something is already serving. It also no longer carries a fixed control-channel token in a
    world-readable plist, which handed the Handshake's secret to the very processes it refuses.

    Only affects people who installed the agent; it is not part of the packaged app.

Internal

  • The CI secret scan had been failing for weeks on two key-shaped test fixtures in the phone's
    scrubber test — placeholders it needs in order to prove it redacts them. Allowlisted like the
    server's equivalent. Worth knowing that it did not reproduce on a current local gitleaks; CI
    pins an older version whose rules still flag them.

Security

  • The same hole reached further on unreleased code — the GitHub, Slack, Notion, Linear and Vercel
    connectors were built on the same unguarded reads. Those landed after v3.1.0 and were fixed
    before they ever shipped, so no released build ever exposed them. Recorded here because the
    fix is public and the shape is worth knowing.

🔒 Verify your download (SHA-256)

The one-paste installers verify this automatically. To check by hand, compute the hash and match:

  • macOS/Linux: shasum -a 256 <file>
  • Windows (PowerShell): Get-FileHash <file> -Algorithm SHA256
c0792fead58765dcad9ca7a04a03dd3c26f06d0e61b3086d53f3219750e6170f  SAM-3.1.1-arm64.dmg
6eb597accefc90b8dbc119c01fef65926563cfcfa408dc58c45f0e28f7cf6a14  SAM-3.1.1.dmg
19404714a90b91be5d7cc1e55658cf78fe295f9a58e71ee70556c12708ef5bb2  SAM-Setup-3.1.1.exe
684237287cc244c0d0250a5cd83683c703b3695859f331efa7502f455cf88427  SAM-3.1.1.AppImage
6c98cc3a36aeb188c7ef3c6f970a7c36241aad0b0835b56f2603db1e7db24487  sam_3.1.1_amd64.deb