From af991e8dc3899c91012f8c5621568ab7beee30fb Mon Sep 17 00:00:00 2001 From: Nathan Henrie Date: Sat, 3 May 2025 11:49:36 -0600 Subject: [PATCH] Separate flags from positional args with `--` This prevents interpreting filenames with leading `-` as flags. Add a regression test for this behavior. Fixes https://github.com/ryantm/agenix/issues/325 --- example/-leading-hyphen-filename.age | 7 +++++++ example/secrets.nix | 1 + pkgs/agenix.sh | 20 ++++++++++---------- test/integration.nix | 8 ++++++-- 4 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 example/-leading-hyphen-filename.age diff --git a/example/-leading-hyphen-filename.age b/example/-leading-hyphen-filename.age new file mode 100644 index 0000000..eb870dd --- /dev/null +++ b/example/-leading-hyphen-filename.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 V3XmEA zirqdzZZ1E+sedBn7fbEHq4ntLEkokZ4GctarBBOHXY +Rvs5YHaAUeCZyNwPedubPcHClWYIuXXWA5zadXPWY6w +-> ssh-ed25519 KLPP8w BVp4rDkOYSQyn8oVeHFeinSqW+pdVtxBF9+5VM1yORY +bMwppAi8Nhz0328taU4AzUkTVyWtSLvFZG6c5W/Fs78 +--- xCbqLhXAcOziO2wmbjTiSQfZvt5Rlsc4SCvF+iEzpQA +ôKB£î/²ZÅÈrÙ%¾à4¡´—Mq5×Ô_ÌÂÝ’‹†ã„Ò11 ܨqM;& ¢‡LríÂÒføû”]>N \ No newline at end of file diff --git a/example/secrets.nix b/example/secrets.nix index 2910329..4a43b3b 100644 --- a/example/secrets.nix +++ b/example/secrets.nix @@ -5,4 +5,5 @@ in { "secret1.age".publicKeys = [user1 system1]; "secret2.age".publicKeys = [user1]; "passwordfile-user1.age".publicKeys = [user1 system1]; + "-leading-hyphen-filename.age".publicKeys = [user1 system1]; } diff --git a/pkgs/agenix.sh b/pkgs/agenix.sh index 3d0415e..628a511 100644 --- a/pkgs/agenix.sh +++ b/pkgs/agenix.sh @@ -105,11 +105,11 @@ RULES=${RULES:-./secrets.nix} function cleanup { if [ -n "${CLEARTEXT_DIR+x}" ] then - rm -rf "$CLEARTEXT_DIR" + rm -rf -- "$CLEARTEXT_DIR" fi if [ -n "${REENCRYPTED_DIR+x}" ] then - rm -rf "$REENCRYPTED_DIR" + rm -rf -- "$REENCRYPTED_DIR" fi } trap "cleanup" 0 2 3 15 @@ -141,7 +141,7 @@ function decrypt { err "No identity found to decrypt $FILE. Try adding an SSH key at $HOME/.ssh/id_rsa or $HOME/.ssh/id_ed25519 or using the --identity flag to specify a file." fi - @ageBin@ "${DECRYPT[@]}" "$FILE" || exit 1 + @ageBin@ "${DECRYPT[@]}" -- "$FILE" || exit 1 fi } @@ -150,14 +150,14 @@ function edit { KEYS=$(keys "$FILE") || exit 1 CLEARTEXT_DIR=$(@mktempBin@ -d) - CLEARTEXT_FILE="$CLEARTEXT_DIR/$(basename "$FILE")" + CLEARTEXT_FILE="$CLEARTEXT_DIR/$(basename -- "$FILE")" DEFAULT_DECRYPT+=(-o "$CLEARTEXT_FILE") decrypt "$FILE" "$KEYS" || exit 1 - [ ! -f "$CLEARTEXT_FILE" ] || cp "$CLEARTEXT_FILE" "$CLEARTEXT_FILE.before" + [ ! -f "$CLEARTEXT_FILE" ] || cp -- "$CLEARTEXT_FILE" "$CLEARTEXT_FILE.before" - [ -t 0 ] || EDITOR='cp /dev/stdin' + [ -t 0 ] || EDITOR='cp -- /dev/stdin' $EDITOR "$CLEARTEXT_FILE" @@ -166,7 +166,7 @@ function edit { warn "$FILE wasn't created." return fi - [ -f "$FILE" ] && [ "$EDITOR" != ":" ] && @diffBin@ -q "$CLEARTEXT_FILE.before" "$CLEARTEXT_FILE" && warn "$FILE wasn't changed, skipping re-encryption." && return + [ -f "$FILE" ] && [ "$EDITOR" != ":" ] && @diffBin@ -q -- "$CLEARTEXT_FILE.before" "$CLEARTEXT_FILE" && warn "$FILE wasn't changed, skipping re-encryption." && return ENCRYPT=() while IFS= read -r key @@ -177,15 +177,15 @@ function edit { done <<< "$KEYS" REENCRYPTED_DIR=$(@mktempBin@ -d) - REENCRYPTED_FILE="$REENCRYPTED_DIR/$(basename "$FILE")" + REENCRYPTED_FILE="$REENCRYPTED_DIR/$(basename -- "$FILE")" ENCRYPT+=(-o "$REENCRYPTED_FILE") @ageBin@ "${ENCRYPT[@]}" <"$CLEARTEXT_FILE" || exit 1 - mkdir -p "$(dirname "$FILE")" + mkdir -p -- "$(dirname -- "$FILE")" - mv -f "$REENCRYPTED_FILE" "$FILE" + mv -f -- "$REENCRYPTED_FILE" "$FILE" } function rekey { diff --git a/test/integration.nix b/test/integration.nix index e0ee85a..0871ffa 100644 --- a/test/integration.nix +++ b/test/integration.nix @@ -24,8 +24,9 @@ pkgs.nixosTest { services.openssh.enable = true; - age.secrets.passwordfile-user1 = { - file = ../example/passwordfile-user1.age; + age.secrets = { + passwordfile-user1.file = ../example/passwordfile-user1.age; + leading-hyphen.file = ../example/-leading-hyphen-filename.age; }; age.identityPaths = options.age.identityPaths.default ++ ["/etc/ssh/this_key_wont_exist"]; @@ -71,6 +72,7 @@ pkgs.nixosTest { user = "user1"; password = "password1234"; secret2 = "world!"; + hyphen-secret = "filename started with hyphen"; in '' system1.wait_for_unit("multi-user.target") system1.wait_until_succeeds("pgrep -f 'agetty.*tty1'") @@ -92,6 +94,8 @@ pkgs.nixosTest { system1.wait_for_file("/tmp/2") assert "${secret2}" in system1.succeed("cat /tmp/2") + assert "${hyphen-secret}" in system1.succeed("cat /run/agenix/leading-hyphen") + userDo = lambda input : f"sudo -u user1 -- bash -c 'set -eou pipefail; cd /tmp/secrets; {input}'" before_hash = system1.succeed(userDo('sha256sum passwordfile-user1.age')).split()