feat(updater): give CloseUp its own dedicated Sparkle EdDSA key#7
Conversation
Switch SUPublicEDKey from the key shared with LockIME (keychain account `ed25519`) to a CloseUp-only key generated under account `com.oomol.CloseUp`, so a key compromise or rotation is scoped to this app alone. New public key: 87rgPjb6NxOUggn75Yv7iRylvHlLoViERAv3tRJ5JvM= Breaking by design: builds shipped with the old shared key (<=0.1.0-beta.2, all already orphaned) cannot verify updates signed by the new key, so they will not auto-update — acceptable since there are effectively no users yet. The matching private key must be set as the SPARKLE_EDDSA_PRIVATE_KEY secret (generate_keys --account com.oomol.CloseUp -x <fresh-path>).
Summary by CodeRabbit
WalkthroughThe PR rotates the Sparkle EdDSA signing key for CloseUp. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches✨ Simplify code
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/RUNBOOK.md`:
- Line 31: The private-key export path in the runbook still uses mktemp -u,
which creates a race-prone pathname instead of a guaranteed private location.
Update the generate_keys -x workflow in the RUNBOOK instructions to use mktemp
-d, then write SPARKLE_EDDSA_PRIVATE_KEY into a file inside that temporary
directory and clean it up afterward. Keep the fix localized to the key-export
steps around generate_keys and the related cleanup commands.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0623e6cf-b3cb-4e67-9b2d-ddb0971916b0
📒 Files selected for processing (2)
Sources/CloseUp/Info.plistdocs/RUNBOOK.md
| ACCT=com.oomol.CloseUp | ||
| "$GENKEYS" --account "$ACCT" -p # print CloseUp's public key (must match Info.plist SUPublicEDKey) | ||
| "$GENKEYS" --account "$ACCT" # generate it (only if it does NOT exist yet); prints the public key | ||
| "$GENKEYS" --account "$ACCT" -x "$(mktemp -u)" # export the private key to a fresh path for the CI secret, then delete it |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## docs/RUNBOOK.md relevant lines\n'
nl -ba docs/RUNBOOK.md | sed -n '20,45p'
printf '\n## search for mktemp -u references\n'
rg -n "mktemp -u|generate_keys|SPARKLE_EDDSA_PRIVATE_KEY" docs .github -S
printf '\n## workflow relevant lines\n'
nl -ba .github/workflows/build-publish.yml | sed -n '170,215p'Repository: oomol-lab/CloseUp
Length of output: 230
🏁 Script executed:
#!/bin/bash
set -euo pipefail
tmp="$(mktemp -u)"
printf 'candidate=%s\n' "$tmp"
if [ -e "$tmp" ]; then
printf 'exists=1\n'
else
printf 'exists=0\n'
fi
dir="$(mktemp -d)"
printf 'dir=%s\n' "$dir"
if [ -d "$dir" ]; then
printf 'dir_exists=1\n'
else
printf 'dir_exists=0\n'
fi
rmdir "$dir"Repository: oomol-lab/CloseUp
Length of output: 231
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## docs/RUNBOOK.md relevant lines\n'
sed -n '20,45p' docs/RUNBOOK.md | cat -n
printf '\n## search for mktemp -u references\n'
rg -n "mktemp -u|generate_keys|SPARKLE_EDDSA_PRIVATE_KEY" docs .github -S
printf '\n## workflow relevant lines\n'
sed -n '170,215p' .github/workflows/build-publish.yml | cat -nRepository: oomol-lab/CloseUp
Length of output: 5809
Avoid mktemp -u for the private-key export path.
Lines 31 and 36-39 leave a TOCTOU window: mktemp -u only picks a pathname, so another process can create or symlink it before generate_keys -x writes SPARKLE_EDDSA_PRIVATE_KEY. Use mktemp -d and export into a file inside that private temp directory instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/RUNBOOK.md` at line 31, The private-key export path in the runbook still
uses mktemp -u, which creates a race-prone pathname instead of a guaranteed
private location. Update the generate_keys -x workflow in the RUNBOOK
instructions to use mktemp -d, then write SPARKLE_EDDSA_PRIVATE_KEY into a file
inside that temporary directory and clean it up afterward. Keep the fix
localized to the key-export steps around generate_keys and the related cleanup
commands.
Switch SUPublicEDKey from the LockIME-shared key (account ed25519) to a CloseUp-only key under account com.oomol.CloseUp (new pubkey 87rgPjb6NxOUggn75Yv7iRylvHlLoViERAv3tRJ5JvM=), so compromise/rotation is scoped to this app. Breaking by design: builds with the old key (<=0.1.0-beta.2, already orphaned / no users) won't auto-update and must be re-downloaded. To land: set SPARKLE_EDDSA_PRIVATE_KEY to the new private key, merge, cut 0.1.0-beta.3. RUNBOOK 1.1 updated to require --account.