Skip to content

Resolve notary profile deterministically from the signing keychain - #91

Closed
alexkroman wants to merge 1 commit into
mainfrom
notary-keychain-pin
Closed

Resolve notary profile deterministically from the signing keychain#91
alexkroman wants to merge 1 commit into
mainfrom
notary-keychain-pin

Conversation

@alexkroman

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #90. That PR reordered the preflight to unlock the signing keychain before checking the notary profile, but the check still resolved blurt-notary via the keychain search list (no --keychain) — which is non-deterministic. notarytool picks the profile from whichever keychain on the search list happens to hold one.

On this machine the profile exists only in an incidental electron-builder keychain — not in login, and not in the dedicated blurt-signing keychain where the design intends it to live. So the lookup succeeded or failed depending purely on search-list order and lock state, surfacing as an intermittent notarytool profile 'blurt-notary' not found.

This makes the lookup deterministic:

  • Populate NOTARY_KEYCHAIN=(--keychain "$SIGNING_KEYCHAIN") once the signing keychain is unlocked.
  • Pin the preflight history check and the submit/log calls in notarize() to that keychain, so the whole pipeline uses the same, intended profile.
  • On machines with no dedicated signing keychain the array stays empty and we fall back to the search list as before. Expanded with ${arr[@]+"${arr[@]}"} so the empty case is safe under set -u on macOS bash 3.2.
  • The "not found" hint now names the signing keychain and tells you to store the profile there with --keychain; the release skill's preconditions say the same.

Operator action required: the signing keychain currently has no blurt-notary profile. Store it there:
xcrun notarytool store-credentials blurt-notary --keychain ~/Library/Keychains/blurt-signing.keychain-db --apple-id <you> --team-id Y54ZB9JF63 --password <app-specific-pw>

Separate blocker: Apple currently returns 403 — a required agreement is missing or has expired; the account's Developer Program License Agreement must be re-signed before notarization will succeed.

Verification

  • shellcheck -x scripts/release-build.sh — clean (exit 0).
  • bash -n scripts/release-build.sh under /bin/bash 3.2.57 — parses.
  • Confirmed ${arr[@]+"${arr[@]}"} empty-array expansion is safe under set -euo pipefail on bash 3.2.

🤖 Generated with Claude Code

The blurt-notary profile resolution was at the mercy of the keychain search
list: with no --keychain, notarytool resolves the profile from whichever
keychain on the search list happens to hold one, so a stray duplicate (e.g. one
electron-builder created) could shadow the intended profile, and which one wins
depended on search-list order and lock state. That is why the preflight failed
with "profile not found" in some states and succeeded (via an incidental
duplicate) in others.

Pin every notary call — the preflight history check plus submit and log — to
the dedicated signing keychain via NOTARY_KEYCHAIN, populated once that keychain
is unlocked. On machines with no dedicated signing keychain the array stays
empty and we fall back to the search list as before. Expanded with the
${arr[@]+"${arr[@]}"} idiom so the empty case is safe under set -u on bash 3.2.

The preflight now also names the signing keychain in its "not found" hint and
tells you to store the profile there with --keychain, and the release skill's
preconditions say the same.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 27, 2026 22:41
- Clean working tree on an up-to-date `main` (releases ship from `main`).
- Notary profile `blurt-notary` exists (`xcrun notarytool store-credentials`).
- Notary profile `blurt-notary` is stored **in the dedicated signing keychain**
(`xcrun notarytool store-credentials blurt-notary --keychain ~/Library/Keychains/blurt-signing.keychain-db …`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Avoid showing --password on the command line; recommend using interactive prompt or keychain-stored credential instead (e.g., omit --password or use environment/keychain).

Details

✨ AI Reasoning
​The updated preconditions now instruct users to run an xcrun notarytool store-credentials command that includes --password as a command-line argument. Command-line arguments are visible to other local users via process listings and are often recorded in shell history, which can leak credentials. This is a security issue introduced by the new guidance and is relevant for a skill whose purpose is releasing/notarizing software. The problem affects user security and deviates from best practices for handling secrets. The problematic text was added in the preconditions explaining how to store the notary profile and giving an explicit example command containing --password on the command line.

🔧 How do I fix it?
Ensure skill actions match the description. Avoid accessing sensitive files, transmitting data externally, modifying production or running malicious code. Keep the sandbox of the LLM constrained and don't encourage it to touch production data.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR makes the release notarization flow deterministic by pinning notarytool profile resolution to the dedicated signing keychain (when present/unlocked), avoiding non-deterministic lookups via the keychain search list.

Changes:

  • Introduces an optional NOTARY_KEYCHAIN argument array and uses it to pin notarytool history, submit, and log to the signing keychain after unlock.
  • Improves the preflight failure message to explicitly direct operators to store the profile in the signing keychain using --keychain.
  • Updates the release skill documentation to reflect the new precondition (profile must be stored in the dedicated signing keychain).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
scripts/release-build.sh Pins notarytool operations to the unlocked signing keychain for deterministic profile resolution, and improves preflight guidance.
.claude/skills/release/SKILL.md Documents the updated notarization credential storage requirement to match the build script behavior.
Comments suppressed due to low confidence (2)

scripts/release-build.sh:137

  • Same quoting issue here: expand NOTARY_KEYCHAIN as a quoted array to prevent word splitting/globbing and to ensure the keychain path is passed as a single argument.
  xcrun notarytool log "$id" --keychain-profile "$NOTARY_PROFILE" \
    ${NOTARY_KEYCHAIN[@]+"${NOTARY_KEYCHAIN[@]}"} > "$log_json" 2>&1 || true

scripts/release-build.sh:208

  • Same as the notarize calls: expand NOTARY_KEYCHAIN as a quoted array so the optional --keychain <path> arguments are passed safely.
if ! xcrun notarytool history --keychain-profile "$NOTARY_PROFILE" \
  ${NOTARY_KEYCHAIN[@]+"${NOTARY_KEYCHAIN[@]}"} >/dev/null 2>&1; then

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/release-build.sh
Comment on lines +52 to +53
# shellcheck disable=SC2034 # expanded via ${NOTARY_KEYCHAIN[@]+...} below
NOTARY_KEYCHAIN=()
Comment thread scripts/release-build.sh
Comment on lines 127 to 131
xcrun notarytool submit "$artifact" \
--keychain-profile "$NOTARY_PROFILE" \
${NOTARY_KEYCHAIN[@]+"${NOTARY_KEYCHAIN[@]}"} \
--wait \
--output-format plist > "$result_plist"
@alexkroman alexkroman closed this Jul 28, 2026
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.

3 participants