Prevent empty drive encryption passwords (#6306)

* Prevent empty drive encryption passwords

* Use sudo, quote the confirmation compare, and cover mismatches in test

The unquoted [[ $new_password == $confirmation ]] made the confirmation
a glob pattern, so a confirmation like * matched any password. And pkexec
brought nothing over the repo-standard sudo here while failing outright
in sessions without a polkit agent.

Verified against a loopback LUKS device: new key lands from stdin without
a trailing newline while the current passphrase is prompted on the tty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: mplaczek99 <mplaczek99@gmail.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Michael Placzek
2026-07-18 18:21:39 -07:00
committed by GitHub
co-authored by Claude Fable 5 mplaczek99 David Heinemeier Hansson
parent afa2839a5a
commit 58e13cd079
2 changed files with 58 additions and 1 deletions
+9 -1
View File
@@ -13,8 +13,16 @@ if [[ -n $encrypted_drives ]]; then
fi
if [[ -n $drive_to_change ]]; then
new_password=$(gum input --password --header "New encryption password") || exit 1
[[ -n $new_password ]] || { echo "Password cannot be empty."; exit 1; }
confirmation=$(gum input --password --header "Confirm new encryption password") || exit 1
[[ $new_password == "$confirmation" ]] || { echo "Passwords do not match."; exit 1; }
echo "Changing full-disk encryption password for $drive_to_change"
sudo cryptsetup luksChangeKey --pbkdf argon2id --iter-time 2000 "$drive_to_change"
# The new key travels over stdin and reaches cryptsetup as a keyfile via
# <(cat), leaving the tty free for the current-passphrase prompt.
printf "%s" "$new_password" | sudo bash -c 'exec cryptsetup luksChangeKey --pbkdf argon2id --iter-time 2000 "$1" <(cat) </dev/tty' bash "$drive_to_change"
else
echo "No drive selected."
fi
+49
View File
@@ -0,0 +1,49 @@
#!/bin/bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
tmp_dir=$(mktemp -d)
trap 'rm -r "$tmp_dir"' EXIT
cat >"$tmp_dir/blkid" <<'EOF'
#!/bin/bash
echo /dev/test-luks
EOF
cat >"$tmp_dir/gum" <<'EOF'
#!/bin/bash
head -n 1 "$TEST_INPUTS"
sed -i '1d' "$TEST_INPUTS"
EOF
cat >"$tmp_dir/sudo" <<'EOF'
#!/bin/bash
printf '%s\n' "$@" >"$TEST_ARGS"
cat >"$TEST_STDIN"
EOF
chmod +x "$tmp_dir/blkid" "$tmp_dir/gum" "$tmp_dir/sudo"
export PATH="$tmp_dir:$ROOT/bin:$PATH"
export TEST_ARGS="$tmp_dir/args" TEST_INPUTS="$tmp_dir/inputs" TEST_STDIN="$tmp_dir/stdin"
printf '\n' >"$TEST_INPUTS"
if "$ROOT/bin/omarchy-drive-password" >/dev/null; then
fail "drive password rejects an empty passphrase"
fi
[[ ! -e $TEST_ARGS ]] || fail "drive password does not run cryptsetup for an empty passphrase"
printf 'secret123\n*\n' >"$TEST_INPUTS"
if "$ROOT/bin/omarchy-drive-password" >/dev/null; then
fail "drive password rejects a mismatched confirmation"
fi
[[ ! -e $TEST_ARGS ]] || fail "drive password does not run cryptsetup for a mismatched confirmation"
printf 'new password\nnew password\n' >"$TEST_INPUTS"
"$ROOT/bin/omarchy-drive-password" >/dev/null
[[ $(<"$TEST_STDIN") == "new password" ]] || fail "drive password passes the validated passphrase without a newline"
grep -F 'cryptsetup luksChangeKey' "$TEST_ARGS" >/dev/null || fail "drive password changes the LUKS key"
grep -Fx /dev/test-luks "$TEST_ARGS" >/dev/null || fail "drive password targets the selected drive"
pass "drive password rejects empty and mismatched passphrases and passes validated input to cryptsetup"