mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-28 21:06:56 -06:00
* security: write files atomically through an exclusive temp file (CWE-59, CWE-377) Save, export, plot, autosave and the audit log each wrote their output by putting bytes in a predictable sibling temporary path (`<path>.cadcraft-tmp`, `<recovery>.tmp`, or the companion `.adt`) and renaming it over the real file. Opening that pre-existing temporary path for a truncating write follows a symlink planted there by another local user, letting them redirect the write onto any file the victim can write before the rename. Add a shared `atomic_write` helper that creates a fresh temporary file with `create_new` (O_CREAT|O_EXCL) in the destination directory, writes through the retained handle, flushes/syncs, and atomically renames it into place. An existing entry (symlink or not) makes the exclusive create fail instead of being followed. Route autosave, save, export, plot and the audit log through it. The macOS CI cert importer likewise wrote the decoded PKCS#12 container to a fixed name in a possibly shared temp directory; it now creates a private per-run directory with `mktemp -d` and creates the file with noclobber. Addresses findings rows 1, 25, 40 (CWE-59) and 19 (CWE-377). * fix: preserve permissions during atomic replacement * fix: restrict temporary permissions during exclusive creation --------- Co-authored-by: skylartaylor <26588250+skylartaylor@users.noreply.github.com>
56 lines
2.6 KiB
Bash
Executable File
56 lines
2.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# CI only: import the Developer ID certificate into a temporary keychain so codesign can use it.
|
|
#
|
|
# Inputs (env): APPLE_CERTIFICATE (base64 .p12), APPLE_CERTIFICATE_PASSWORD, KEYCHAIN_PASSWORD
|
|
# (optional; random if unset), RUNNER_TEMP (or TMPDIR).
|
|
# Outputs: MACOS_SIGN_IDENTITY (SHA-1 of the identity) and MACOS_KEYCHAIN, appended to
|
|
# $GITHUB_ENV when running in Actions, otherwise printed.
|
|
#
|
|
# Missing certificate: prints a warning and exits 0, so package.sh falls back to ad-hoc signing.
|
|
set -euo pipefail
|
|
umask 077
|
|
# shellcheck source=../env.sh
|
|
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
|
|
|
|
if [ -z "${APPLE_CERTIFICATE:-}" ]; then
|
|
warn "APPLE_CERTIFICATE is not set: macOS builds will be ad-hoc signed and not notarized"
|
|
exit 0
|
|
fi
|
|
|
|
TMP="${RUNNER_TEMP:-${TMPDIR:-/tmp}}"
|
|
# Create a private per-run directory (mode 0700 via the umask above) so the decoded signing
|
|
# container cannot be read by, or pre-created by, another local user in a shared temp directory.
|
|
CERT_DIR="$(mktemp -d "$TMP/cadcraft-signing.XXXXXXXX")"
|
|
KEYCHAIN="$TMP/cadcraft-signing.keychain-db"
|
|
CERT="$CERT_DIR/cadcraft-signing.p12"
|
|
KC_PASS="${KEYCHAIN_PASSWORD:-$(openssl rand -hex 24)}"
|
|
|
|
trap 'rm -f "$CERT"; rm -rf "$CERT_DIR"' EXIT
|
|
# Create the certificate file privately before writing, refusing to follow a pre-existing entry.
|
|
( set -C; : >"$CERT" )
|
|
printf '%s' "$APPLE_CERTIFICATE" | base64 --decode >"$CERT"
|
|
security create-keychain -p "$KC_PASS" "$KEYCHAIN"
|
|
security set-keychain-settings -lut 21600 "$KEYCHAIN"
|
|
security unlock-keychain -p "$KC_PASS" "$KEYCHAIN"
|
|
security import "$CERT" -P "${APPLE_CERTIFICATE_PASSWORD:-}" -T /usr/bin/codesign -T /usr/bin/security -t cert -f pkcs12 -k "$KEYCHAIN"
|
|
rm -f "$CERT"
|
|
# Let codesign use the key without a UI prompt.
|
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KC_PASS" "$KEYCHAIN" >/dev/null
|
|
# Put it on the search list (keeping the login keychain) so codesign and notarytool find it.
|
|
# shellcheck disable=SC2046
|
|
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | tr -d '"')
|
|
|
|
IDENTITY="$(security find-identity -v -p codesigning "$KEYCHAIN" | awk '/Developer ID Application/ { print $2; exit }')"
|
|
if [ -z "$IDENTITY" ]; then
|
|
security find-identity -v -p codesigning "$KEYCHAIN" >&2
|
|
echo "error: no 'Developer ID Application' identity in APPLE_CERTIFICATE" >&2
|
|
exit 1
|
|
fi
|
|
echo "Imported signing identity $IDENTITY"
|
|
if [ -n "${GITHUB_ENV:-}" ]; then
|
|
{ echo "MACOS_SIGN_IDENTITY=$IDENTITY"; echo "MACOS_KEYCHAIN=$KEYCHAIN"; } >>"$GITHUB_ENV"
|
|
else
|
|
echo "MACOS_SIGN_IDENTITY=$IDENTITY"
|
|
echo "MACOS_KEYCHAIN=$KEYCHAIN"
|
|
fi
|