From 20286add5f7e01fb8ee008bcda8b64489aa19de1 Mon Sep 17 00:00:00 2001 From: noctuum <25441068+noctuum@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:26:58 +0500 Subject: [PATCH] fix(setup): shell-quote saved config values --- docs/SETUP.md | 10 +++++----- scripts/setup.sh | 13 +++++++------ tests/gpg-flow.bats | 4 ++-- tests/setup.bats | 41 +++++++++++++++++++++++++++++++++-------- 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/docs/SETUP.md b/docs/SETUP.md index 4f6d203..aa770cd 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -240,13 +240,13 @@ Steps can be combined: ## Configuration file -Setup saves its state to `.aurtomator.conf` in the project root. The scripts source it as a shell file. +Setup saves its state to `.aurtomator.conf` in the project root. The scripts source it as a shell file, so `setup.sh` writes every value shell-quoted, and a `"`, `$` or backtick in a name stays part of the name. A file from an older version, with double quotes, still loads. ```bash -GIT_AUTHOR_NAME="Jane Doe" -GIT_AUTHOR_EMAIL="jane@example.com" -GPG_KEY_ID="ABCDEF1234567890" -AUR_SSH_KEY="/home/jane/.ssh/aur_ed25519" +GIT_AUTHOR_NAME='Jane Doe' +GIT_AUTHOR_EMAIL='jane@example.com' +GPG_KEY_ID='ABCDEF1234567890' +AUR_SSH_KEY='/home//.ssh/aur_ed25519' ``` | Variable | Description | diff --git a/scripts/setup.sh b/scripts/setup.sh index 372ca6c..b3e49d4 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -85,13 +85,14 @@ load_config() { fi } +# load_config sources the file, so each value is written shell-quoted save_config() { - cat >"$CONFIG_FILE" <"$CONFIG_FILE" ok "Config saved to .aurtomator.conf" } diff --git a/tests/gpg-flow.bats b/tests/gpg-flow.bats index 06a45fe..ce7e5ee 100644 --- a/tests/gpg-flow.bats +++ b/tests/gpg-flow.bats @@ -338,7 +338,7 @@ EOF --gpg-key "$NOPASS_SUBKEY_ID" --non-interactive [ "$status" -eq 0 ] [[ "$output" == *"no passphrase, ready for CI"* ]] - grep -q "GPG_KEY_ID=\"$NOPASS_SUBKEY_ID\"" "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "GPG_KEY_ID='$NOPASS_SUBKEY_ID'" "$TEST_TMPDIR/.aurtomator.conf" } @test "gpg-real: config clears GPG_KEY_ID when passphrase key skipped" { @@ -352,5 +352,5 @@ EOF run "$TEST_TMPDIR/scripts/setup.sh" gpg \ --gpg-key "$WITHPASS_SUBKEY_ID" --non-interactive [ "$status" -eq 0 ] - grep -q 'GPG_KEY_ID=""' "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "GPG_KEY_ID=''" "$TEST_TMPDIR/.aurtomator.conf" } diff --git a/tests/setup.bats b/tests/setup.bats index 759ea97..6afcca6 100644 --- a/tests/setup.bats +++ b/tests/setup.bats @@ -253,8 +253,8 @@ EOF --non-interactive [ "$status" -eq 0 ] [[ "$output" == *"Git author: Jane Doe"* ]] - grep -q 'GIT_AUTHOR_NAME="Jane Doe"' "$TEST_TMPDIR/.aurtomator.conf" - grep -q 'GIT_AUTHOR_EMAIL="jane@example.com"' "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "GIT_AUTHOR_NAME='Jane Doe'" "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "GIT_AUTHOR_EMAIL='jane@example.com'" "$TEST_TMPDIR/.aurtomator.conf" } @test "setup identity: fails without git name in non-interactive" { @@ -384,6 +384,31 @@ EOF grep -q "GIT_AUTHOR_EMAIL" "$TEST_TMPDIR/.aurtomator.conf" } +@test "setup: saved values with shell characters come back unchanged" { + local name="x\"; touch $TEST_TMPDIR/injected; :\"" + local email="j\`touch $TEST_TMPDIR/injected\`@example.com" + local gpg_key="\$(touch $TEST_TMPDIR/injected)" + local ssh_key="/keys/it's a \$key\\path" + "$TEST_TMPDIR/scripts/setup.sh" identity \ + --git-name "$name" --git-email "$email" \ + --gpg-key "$gpg_key" --ssh-key "$ssh_key" \ + --non-interactive + + run "$TEST_TMPDIR/scripts/setup.sh" identity --non-interactive + [ "$status" -eq 0 ] + [[ "$output" == *"Git author: $name <$email>"* ]] + + # lib.sh sources the file the same way + run bash -c 'source "$1"; printf "%s\n" "$GIT_AUTHOR_NAME" "$GIT_AUTHOR_EMAIL" "$GPG_KEY_ID" "$AUR_SSH_KEY"' \ + _ "$TEST_TMPDIR/.aurtomator.conf" + [ "$status" -eq 0 ] + [ "${lines[0]}" = "$name" ] + [ "${lines[1]}" = "$email" ] + [ "${lines[2]}" = "$gpg_key" ] + [ "${lines[3]}" = "$ssh_key" ] + [ ! -e "$TEST_TMPDIR/injected" ] +} + @test "setup identity: CLI flags override saved config" { write_full_config @@ -392,8 +417,8 @@ EOF --non-interactive [ "$status" -eq 0 ] [[ "$output" == *"Git author: Jane Doe "* ]] - grep -q 'GIT_AUTHOR_NAME="Jane Doe"' "$TEST_TMPDIR/.aurtomator.conf" - grep -q 'GIT_AUTHOR_EMAIL="jane@example.com"' "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "GIT_AUTHOR_NAME='Jane Doe'" "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "GIT_AUTHOR_EMAIL='jane@example.com'" "$TEST_TMPDIR/.aurtomator.conf" } @test "setup gpg: --gpg-key overrides saved key" { @@ -402,7 +427,7 @@ EOF run "$TEST_TMPDIR/scripts/setup.sh" gpg --gpg-key VALIDKEY123 --non-interactive [ "$status" -eq 0 ] [[ "$output" == *"GPG key: VALIDKEY123"* ]] - grep -q 'GPG_KEY_ID="VALIDKEY123"' "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "GPG_KEY_ID='VALIDKEY123'" "$TEST_TMPDIR/.aurtomator.conf" } @test "setup ssh: --ssh-key overrides saved path" { @@ -415,7 +440,7 @@ EOF --non-interactive [ "$status" -eq 0 ] [[ "$output" == *"SSH key: $TEST_TMPDIR/ssh/aur.pem"* ]] - grep -q "AUR_SSH_KEY=\"$TEST_TMPDIR/ssh/aur.pem\"" "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "AUR_SSH_KEY='$TEST_TMPDIR/ssh/aur.pem'" "$TEST_TMPDIR/.aurtomator.conf" } # === Verify step === @@ -473,8 +498,8 @@ EOF --ssh-key "$TEST_TMPDIR/ssh/aur.pem" --non-interactive [ "$status" -eq 1 ] [[ "$output" == *"1 issue(s) found."* ]] - grep -q 'GIT_AUTHOR_NAME="Jane Doe"' "$TEST_TMPDIR/.aurtomator.conf" - grep -q "AUR_SSH_KEY=\"$TEST_TMPDIR/ssh/aur.pem\"" "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "GIT_AUTHOR_NAME='Jane Doe'" "$TEST_TMPDIR/.aurtomator.conf" + grep -qx "AUR_SSH_KEY='$TEST_TMPDIR/ssh/aur.pem'" "$TEST_TMPDIR/.aurtomator.conf" } # === Secrets step ===