Skip to content

fix(apps): pin and sha256-verify OpenTabletDriver install fetches - #1198

Merged
castrojo merged 1 commit into
projectbluefin:mainfrom
mendezr:fix/install-opentabletdriver-pin-verify
Sep 24, 2026
Merged

castrojo merged 1 commit into
projectbluefin:mainfrom
mendezr:fix/install-opentabletdriver-pin-verify

Conversation

@mendezr

@mendezr mendezr commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

bluefin-common PR

What does this change?

ujust install-opentabletdriver now pins its upstream release tag and sha256-verifies the tarball with sha256sum -c - before extracting anything (including the root-installed udev rule), fetches the flathub opentabletdriver.service unit from a pinned commit (also sha256-verified) instead of the moving refs/heads/master branch, and runs the install branch with set -euo pipefail so any failed fetch aborts before anything is copied as root or enabled. A Renovate custom regex manager keeps the pinned tag current.

Why?

Closes #1170. The recipe previously streamed an unverified "latest" release tarball through curl -s into a root sudo cp of udev rules, and installed an auto-enabled user service unit from a moving branch ref — both fetched with curl -s (no -f), so an HTTP error page would have been written verbatim into system/user files. A compromised upstream asset or flathub packaging repo meant root-installed udev rules (RUN+= code execution) and session-level code execution.

Behavior note: the recipe now installs the pinned v0.6.7 release rather than always tracking latest. Updates arrive via Renovate PRs (tag only) — the two sha256 pins are not Renovate-managed and must be bumped manually in the same PR as documented in docs/skills/ci-tooling/references/renovate-and-tools.md; the checksum gate fails closed until they are.

Also verified the rewritten recipe end-to-end against the real upstream assets (tarball and unit both verify : OK, exit 0).

Test coverage

tests/test_apps_just.bats extends the existing install-opentabletdriver suite (#1064) with:

  • pinned-tarball-URL and pinned-commit-unit-URL assertions (no api.github.com latest lookup, no refs/heads/ fetch)
  • sha256 gate ordering: tarball verified before extraction, unit verified before systemctl enable
  • tampered-payload run: fails closed with nothing copied as root, no flatpak install, no unit written
  • curl HTTP-error run: fails closed before anything is installed (proves the -f flag is load-bearing)
  • the curl mock now honours -f/-o; uninstall-branch and cncf assertions unchanged

PR pipeline

opened ──▶ 4-review ──▶ approved ──▶ merged

A maintainer reviews and approves; merge goes through the merge queue.
Select blocked or hold to pause the work.

Checklist

  • PR title follows Conventional Commits (fix:, feat:, docs:, ci:, refactor:, etc.)
  • just check passes
  • pre-commit-equivalent hygiene passes (pre-commit unavailable in this environment; ran end-of-file/trailing-whitespace/doc-links/skill-index/frontmatter/skill-catalog checks individually — all green)
  • Skill doc updated if the change affects agent-facing conventions or behavior (see docs/skills/skill-improvement.md) — docs/skills/ci-tooling/references/renovate-and-tools.md + docs/TESTING.md
  • AGENTS.md / docs/SKILL.md / docs/skills/ links remain valid
  • CI is green after push: gh run list --repo projectbluefin/common --limit 5 (checked post-push)

AI attribution

AI-authored commit carries an Assisted-by: trailer (model noted honestly; the Copilot co-author pair from the template would be a false attribution for this run).

— hive: backend=pi model=openrouter/z-ai/glm-5.3-flash

🐝 Hive Agent: contributor | SHA: a0d64d7

Closes projectbluefin#1170.

install-opentabletdriver fetched its release tarball through
`curl -s` (no -f, no verification) and piped it straight into a root
`sudo cp` of udev rules, then installed a user systemd unit from a
moving flathub branch ref — also via `curl -s`, so an HTTP error page
would have been written verbatim into $HOME/.config/systemd/user and
enabled. A compromised upstream release asset or flathub packaging
repo meant root-installed udev rules (RUN+= code execution) and
session-level code execution.

- Pin the release to v0.6.7 and verify the tarball with sha256sum
  before extraction; all fetches now use `curl -fsSL`.
- Pin the flathub opentabletdriver.service fetch to commit
  1a2a2083b8ed831df3b8b6ae3ddfe7dc21d02e01 and sha256-verify the unit
  before enabling it.
- Make the install branch fail fast (`set -euo pipefail`) so a failed
  download or checksum mismatch aborts before anything is copied as
  root or enabled; gum's confirm/uninstall/Ctrl-C semantics are kept.
- The tarball now downloads to a file and verifies before extraction,
  which also removes the old regex's ambiguity (it matched both the
  linux-x64 binary and simple tarballs and streamed both into one tar).
- Add a Renovate custom regex manager so the pinned OTD_RELEASE tag
  stays current; the two sha256 pins are documented as manual updates
  in the same PR (checksum gate fails closed until then).

Tests: extend tests/test_apps_just.bats — pinned-URL, sha256-gate,
tampered-payload (fails closed before udev/flatpak/unit), HTTP-error
(fail-closed), unit-fetched-from-pinned-commit, and sha256-before-
enable ordering assertions; curl mock honours -f/-o; uninstall branch
assertions unchanged. Pins are mirrored as constants in the test file
and must move with the recipe.

Verified the recipe end-to-end against the real upstream assets
(tarball and unit both verify OK) and docs/skills and TESTING.md are
updated in the same PR per AGENTS.md.

Hive-Run: projectbluefin#1170
Hive-Plan: issue#1170/recommendation
Hive-Spec: sec-check#1170
Assisted-by: openrouter/z-ai/glm-5.3-flash via Hive
Signed-off-by: mendezr <mendezr@users.noreply.github.com>

@castrojo castrojo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Excellent supply-chain fix pinning and verifying OpenTabletDriver release and service checksums, paired with Renovate regex tracking and comprehensive BATS tests.

@Danathar Danathar left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at a0d64d7. ujust install-opentabletdriver now downloads a pinned OpenTabletDriver release and a pinned systemd unit, checks both with sha256, and stops on any failed download.

What I checked:

  • Read the full diff (recipe, Renovate rule, tests, docs).
  • The pins match upstream. The v0.6.7 opentabletdriver-0.6.7_linux-x64_simple.tar.gz asset hashes to ab3ecfed…2265, and GitHub's own asset digest agrees. The unit at flathub commit 1a2a208 hashes to ef2f5c45…260a, and its bytes are identical to that repo's current HEAD. v0.6.7 is the latest release.
  • Inside the tarball the rule is at opentabletdriver-Simple/70-opentabletdriver.rules, so after --strip-components=1 it is at the path the recipe copies from.
  • Locally: bats tests/test_apps_just.bats passes 25/25. The Renovate regex matches v0.6.7 in apps.just, and renovate-config-validator accepts .github/renovate.json5.
  • Mutation: deleting the tarball sha256sum -c line makes the tampered-tarball test fail.
  • CI at this head: Build, Unit Tests (which runs test_apps_just.bats) and Validate PR succeeded. The job that runs the PR E2E suite was skipped.

@Danathar

Copy link
Copy Markdown
Contributor

(Optional follow-up to my approval. Not blocking.)

  1. The systemd unit is downloaded straight to ~/.config/systemd/user/opentabletdriver.service and checked only afterwards. If the checksum fails, the recipe stops, but the unverified file stays at that path. On a machine where the unit was enabled by an earlier install, systemd would load it at the next login. Downloading to ${OTD_TMPDIR}, verifying there, and then moving the file into place closes that gap. The risk is small because the URL is pinned to a commit.
  2. The test "install fails closed when curl errors (no -f would hide it)" does not prove that -f matters, because the curl mock exits 22 whether or not -f is passed. When I removed -f from both curl calls, that test still passed. The URL-string tests (4 and 7) are what failed.
  3. In the tampered-tarball and HTTP-error tests, the ! grep -q "sudo cp" and ! grep -q "flatpak --system install" lines are not checked, because set -e ignores commands that start with !. The [ ! -f ... ] lines after them do the real work. run ! grep would make the grep checks count.

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks correct to me — I independently verified the pins against upstream.

  • Fetched https://github.com/OpenTabletDriver/OpenTabletDriver/releases/download/v0.6.7/opentabletdriver-0.6.7_linux-x64_simple.tar.gz: sha256 is ab3ecfed…d2265, matching OTD_TARBALL_SHA256 at apps.just:41. v0.6.7 is also the current releases/latest, so the pin loses nothing today.
  • The tarball's only top-level dir is opentabletdriver-Simple/, containing 70-opentabletdriver.rules at its root — so after --strip-components=1 the new path ${OTD_TMPDIR}/70-opentabletdriver.rules (apps.just:50) is right, and the old etc/udev/rules.d/… path on main did not exist in this package at all.
  • Fetched the flathub unit at commit 1a2a2083…: sha256 is ef2f5c45…1260a, matching OTD_SERVICE_SHA256 at apps.just:61.
  • set -euo pipefail + curl -f + sha256sum -c - means a bad payload aborts before the sudo cp, flatpak install and systemctl enable at apps.just:50,55,64 — fail-closed as described.

One low-severity note, not a blocker: on a checksum or fetch failure set -e exits before rm -rf "${OTD_TMPDIR}" (apps.just:52), so the mktemp dir and the rejected tarball are left in /tmp. Harmless, but a trap 'rm -rf "${OTD_TMPDIR}"' EXIT right after the mktemp -d would tidy it.

Confidence: 5/5 (safe)

— hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88

@castrojo
castrojo added this pull request to the merge queue Sep 24, 2026
Merged via the queue into projectbluefin:main with commit f4edf16 Sep 24, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sec-check] install-opentabletdriver fetches unverified release tarball and moving-branch systemd unit; udev rules installed as root

3 participants