Linux package updates have no integrity check: the .deb and .pkg.tar.zst aren't signed and have no checksum, and the suggested pacman command relies on that #36

Closed
opened 2026-10-05 16:17:33 -04:00 by jared · 1 comment
Owner

Since cinny 27d65911 / 6acdd439, pacman and deb installs get a copy-paste command instead of the in-app updater (update_install_kind, src-tauri/src/lib.rs:202):

curl -LO https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64.pkg.tar.zst && sudo pacman -U ./LotusChat-x86_64.pkg.tar.zst
curl -LO …/LotusChat-x86_64.deb && sudo apt install ./LotusChat-x86_64.deb

Both assets exist on the latest release, and the commands work. But the release publishes no signature or checksum for them. The in-app paths are protected (minisign .sig for the AppImage and NSIS bundles, plus release.json), whereas these two run as root on TLS alone. The pacman variant explicitly downloads first because the package is unsigned: pacman -U <url> requires <url>.sig under RemoteFileSigLevel, and a local file falls under LocalFileSigLevel (optional).

A compromised release asset, a Gitea account with release rights, or a TLS-intercepting proxy therefore gets root on every Linux package user who follows the update prompt. The in-app updater would refuse an unsigned bundle.

Options:

  • Sign the packages in CI: a detached .sig for pacman, either a pacman key users import once or repo-add + a signed repo; for deb, a signed apt repo, or at least dpkg-sig.
  • Or, as a quick improvement, publish SHA256SUMS (minisign-signed with the existing Tauri key) and make the command verify it before installing: curl -LO …/SHA256SUMS && sha256sum -c --ignore-missing SHA256SUMS && sudo pacman -U ….

Also noted (not a bug):

  • Detection is by distro (ID/ID_LIKE in /etc/os-release), not by how the app was installed. An Arch or Ubuntu user running an extracted AppImage (no APPIMAGE env), or a self-built binary in their home directory, is told to install the package.
  • Checking std::env::current_exe() (under /usr/ means package-managed) would be more exact.

Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny 30e2dbcd, cinny-desktop 8f67ec7, element-call 3b0050e8.

Since cinny 27d65911 / 6acdd439, pacman and deb installs get a copy-paste command instead of the in-app updater (`update_install_kind`, src-tauri/src/lib.rs:202): ``` curl -LO https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64.pkg.tar.zst && sudo pacman -U ./LotusChat-x86_64.pkg.tar.zst curl -LO …/LotusChat-x86_64.deb && sudo apt install ./LotusChat-x86_64.deb ``` Both assets exist on the `latest` release, and the commands work. But the release publishes **no signature or checksum** for them. The in-app paths are protected (minisign `.sig` for the AppImage and NSIS bundles, plus `release.json`), whereas these two run as root on TLS alone. The pacman variant explicitly downloads first *because* the package is unsigned: `pacman -U <url>` requires `<url>.sig` under `RemoteFileSigLevel`, and a local file falls under `LocalFileSigLevel` (optional). A compromised release asset, a Gitea account with release rights, or a TLS-intercepting proxy therefore gets root on every Linux package user who follows the update prompt. The in-app updater would refuse an unsigned bundle. **Options:** - Sign the packages in CI: a detached `.sig` for pacman, either a pacman key users import once or `repo-add` + a signed repo; for deb, a signed apt repo, or at least `dpkg-sig`. - Or, as a quick improvement, publish `SHA256SUMS` (minisign-signed with the existing Tauri key) and make the command verify it before installing: `curl -LO …/SHA256SUMS && sha256sum -c --ignore-missing SHA256SUMS && sudo pacman -U …`. **Also noted (not a bug):** - Detection is by distro (`ID`/`ID_LIKE` in `/etc/os-release`), not by how the app was installed. An Arch or Ubuntu user running an *extracted* AppImage (no `APPIMAGE` env), or a self-built binary in their home directory, is told to install the package. - Checking `std::env::current_exe()` (under `/usr/` means package-managed) would be more exact. --- _Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny `30e2dbcd`, cinny-desktop `8f67ec7`, element-call `3b0050e8`._
jared added the priority: lowarea: updatersecurity labels 2026-10-05 16:17:33 -04:00
Author
Owner

Done with the checksum route (decision 2026-10-19). #41 publishes a minisign-signed SHA256SUMS.txt on every release; the first one verifies against the updater key. cinny#422 makes the in-app update command verify the signature and the hash before installing. Signed pacman/apt repos were not set up (they'd need a new signing key).

🤖 Claude Code

Done with the checksum route (decision 2026-10-19). #41 publishes a minisign-signed `SHA256SUMS.txt` on every release; the first one verifies against the updater key. cinny#422 makes the in-app update command verify the signature and the hash before installing. Signed pacman/apt repos were not set up (they'd need a new signing key). 🤖 Claude Code
jared closed this issue 2026-10-19 12:16:09 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny-desktop#36