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
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):
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`._
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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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):Both assets exist on the
latestrelease, and the commands work. But the release publishes no signature or checksum for them. The in-app paths are protected (minisign.sigfor the AppImage and NSIS bundles, plusrelease.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>.sigunderRemoteFileSigLevel, and a local file falls underLocalFileSigLevel(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:
.sigfor pacman, either a pacman key users import once orrepo-add+ a signed repo; for deb, a signed apt repo, or at leastdpkg-sig.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):
ID/ID_LIKEin/etc/os-release), not by how the app was installed. An Arch or Ubuntu user running an extracted AppImage (noAPPIMAGEenv), or a self-built binary in their home directory, is told to install the package.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-desktop8f67ec7, element-call3b0050e8.Done with the checksum route (decision 2026-10-19). #41 publishes a minisign-signed
SHA256SUMS.txton 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