Public Access
Take the release credentials off the command line, where anyone could read them
Three scripts prompted for a secret with Read-Host -AsSecureString or read -s, said in a comment that it therefore never lands in shell history, and then wrote it straight into the arguments of the next process. The comment was true and was answering the wrong question. A command line is not private: on Windows one call to Get-CimInstance Win32_Process hands every argument of every process running as this user to anything that asks, /proc/<pid>/cmdline is world-readable on Linux, and process-creation auditing and EDR agents keep their own copy either way. The values were the Android release signing key's passwords and the forge token — between them the whole capability to ship an update that every installed copy will fetch and run, which ADR 0011 rule 1 and ADR 0013 go to some length to keep off a runner and which was then left in a process listing on a desk. Both replacements are documented features of the tools rather than tricks. The Android passwords use .NET for Android's env: prefix, which puts the name of a variable on the command line and lets MSBuild read the value out of the environment itself. Set immediately before the build and cleared in a finally, so a failed signing does not leave them in the shell for whatever runs next, and -nodeReuse:false so no persistent MSBuild worker outlives the call still holding the inherited copy in its own environment. That prefix is unsupported when AndroidPackageFormat is aab, and the failure is silent — the package would be signed with the literal string "env:DODOSSH_ANDROID_STOREPASS" as its password. So the format is read back and the build stops if it is ever changed, in the same shape as the versionCode guard a few lines above: a wrong release refused here rather than discovered later on somebody's phone. vpk documents VPK_TOKEN as --token's environment fallback, so the flag is simply gone from both desktop scripts and the token never becomes an argument at all. Unset afterwards on the failure path too, which on macOS needs the exit status captured rather than a bare || stop_with. release-macos.sh had the same fault and was missed when the other two were first reported. Its Apple credentials were already right — a notarytool keychain profile rather than --password — and only the forge token was exposed. What this does not claim: an environment block is readable by a process holding rights over this one, the same as its memory is. The comments say so rather than implying the values are now safe. What is bought is real and narrower — off the command line, out of every process listing, out of the audit trail, and out of any log that echoes the invocation. Both PowerShell files parse, all three shell scripts pass bash -n, the AndroidPackageFormat probe evaluates and answers empty so the guard passes, and dotnet build accepts -nodeReuse:false. The signing itself is not exercised here: it needs the release keystore, which by design is not on this machine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
483ae1fed9
commit
597e5ae016
3 files changed
+114
-20
No files matched your search
@@ -38,9 +38,11 @@
|
||||
# xcrun notarytool store-credentials DodoSSH \
|
||||
# --apple-id you@example.com --team-id TEAMID --password <app-specific-password>
|
||||
#
|
||||
# The forge token is the one real secret, and it is prompted for rather than read from a file or the
|
||||
# environment, and only in the phase that needs it — for the reason the Windows script gives: the fewer
|
||||
# minutes a credential that can publish an update spends in a shell's memory the better.
|
||||
# The forge token is the one real secret, and it is prompted for rather than read from a file or an
|
||||
# ambient environment variable, and only in the phase that needs it — for the reason the Windows script
|
||||
# gives: the fewer minutes a credential that can publish an update spends in a shell's memory the better.
|
||||
# It reaches vpk through VPK_TOKEN, exported for that one call and unset afterwards, because the
|
||||
# alternative is --token on a command line that is not private. See the comment at the upload itself.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/release-macos.sh
|
||||
@@ -195,10 +197,18 @@ if [ "$UPLOAD" -eq 1 ]; then
|
||||
# also already hold the Windows package for the same tag, which is the case --merge is really doing
|
||||
# the work for: without it the second platform to publish a given version fails on a release that
|
||||
# exists, and with it the two sit side by side under one tag. --channel keeps the indexes apart.
|
||||
#
|
||||
# No --token in this array, and that is deliberate. It used to be there, and an argument is not a
|
||||
# private place to put a credential: /proc/<pid>/cmdline is world-readable on Linux, `ps` hands out
|
||||
# other processes' arguments freely, and whatever agent is auditing process creation on this machine
|
||||
# keeps its own copy. The comment above is about shell history and was never the whole story.
|
||||
#
|
||||
# vpk documents VPK_TOKEN as --token's environment fallback, so the value never becomes an argument.
|
||||
# Exported for the one call and unset straight after; an environment block is still readable by a
|
||||
# process with rights over this one, but it is out of every process listing and audit log.
|
||||
UPLOAD_ARGS=(
|
||||
upload gitea
|
||||
--repoUrl "$REPO_URL"
|
||||
--token "$TOKEN"
|
||||
--outputDir "$RELEASES_DIR"
|
||||
--channel "$CHANNEL"
|
||||
--releaseName "$TAG"
|
||||
@@ -214,7 +224,15 @@ if [ "$UPLOAD" -eq 1 ]; then
|
||||
esac
|
||||
|
||||
write_step 'Uploading'
|
||||
dotnet vpk "${UPLOAD_ARGS[@]}" || stop_with 'vpk upload failed.'
|
||||
|
||||
# Unset on the way out whether or not the upload worked, so a failed release does not leave the token
|
||||
# sitting in this shell for whatever runs next.
|
||||
export VPK_TOKEN="$TOKEN"
|
||||
vpk_status=0
|
||||
dotnet vpk "${UPLOAD_ARGS[@]}" || vpk_status=$?
|
||||
unset VPK_TOKEN
|
||||
|
||||
[ "$vpk_status" -eq 0 ] || stop_with 'vpk upload failed.'
|
||||
|
||||
write_step "Published $TAG."
|
||||
exit 0
|
||||
|
||||
Reference in new issue
Block a user