Skip to content

CI and release hardening: unenforced lockfile, release.sh key exposure, and settings that leave the signing key reachable #145

Open

Description

@Sadykhzadeh

Checked against main (894ea12) and the repository settings.

In the repository (fixable by a PR)

  1. Cargo.lock is tracked but not enforced. ci.yml, windows-nsis-smoke.yml and the release build all run cargo without --locked, so a lockfile that has drifted gets re-resolved silently. What CI tests is then not what the lockfile says.
  2. Almost no job has timeout-minutes. Only terminal-workspace.yml sets one, so a hung step holds a runner for GitHub's 6-hour default.
  3. No concurrency on release.yml. A tag push and a manual dispatch for the same version race on --clobber uploads to one release, and can pair a .sig with the wrong file. CI on PRs also keeps running superseded commits.
  4. The cargo-audit comment in ci.yml is not true. It says the binary "is built fresh, every run". Without --force, cargo install keeps a binary already on the runner image, and the Consolidate the four open dependency bumps and clear the npm production audit #128 job log shows "cargo-audit v0.22.2 is already installed".
  5. Dependabot has no cooldown. A brand-new release is proposed the moment it is published, and that is the window in which a hijacked package version is live.
  6. scripts/release.sh undoes the key isolation that release.yml has (Sign updater artifacts in a job where the key only sees the verified signer #108):
    • line 164 exports TAURI_SIGNING_PRIVATE_KEY before npx tauri build, so every npm, Vite and build-script step runs with the key in its environment;
    • lines 208-211 pass the key as --private-key "$KEY", which any local user can read from ps;
    • line 252 runs git add -A, which commits whatever untracked file is lying around, a stray key or .env included;
    • lines 226-241 build Python source by interpolating $NOTES, $SIG and $VERSION into '''…''', so a ''' in --notes breaks out of the string;
    • lines 180 and 239 use predictable /tmp paths.
  7. scripts/version.sh puts an unvalidated version into sed. A /, a & or a GNU e flag in the argument corrupts the files or runs a command. It also never updates Cargo.lock, which breaks --locked right after a bump.
  8. The main ruleset requires code-owner review, but there is no CODEOWNERS file, so that setting does nothing.

Repository settings (need an admin; not changeable from a PR)

  1. The updater key is reachable from any push.
    • TAURI_SIGNING_PRIVATE_KEY is a repository secret with no environment, and no ruleset protects v* tags.
    • So anyone with write access, or a leaked token with workflow scope, can push a tag on an unreviewed commit and get a signed update served through latest.json. They can also push a branch whose workflow simply echoes the key.
    • Suggested: a release environment with required reviewers and a deployment policy limited to v* tags, holding both TAURI_SIGNING_* secrets, with environment: release on the sign job. Add a tag ruleset limiting creation, update and deletion of v* to maintainers.
  2. Red CI does not block merges.
    • The main ruleset has no required_status_checks. Main has been red since 894ea12 and merges continued.
    • Suggested: require rust-check, macos-rust-build, frontend-build and security-audit.
  3. Build jobs can rewrite each other's release assets before sign signs them.
    • Every build matrix job has contents: write and GITHUB_TOKEN in the step where npm, build.rs and Vite code run, and releaseDraft: false publishes unsigned assets before signing finishes. The key cannot be stolen this way, but it can be made to sign a tampered file.
    • Suggested follow-up: builds publish through upload-artifact with digests as job outputs, one job creates a draft release, sign verifies digests, and the release is un-drafted only after SHA256SUMS is uploaded.

Activity

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions