From cc326e45a6213360266dda4b30cc68095946d676 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Thu, 1 Oct 2026 15:00:50 -0400 Subject: [PATCH] fix: preserve quoted args when deferring to tagged install script (#5363) The installer word-split the original arguments when piping into a tagged release's `install.sh`, so `-b '/tmp/syft install path'` arrived as three words and the trailing word was treated as a release tag. - argument parsing moved into `parse_install_args` so `main` keeps its original args - tagged script is invoked with `"$@"` instead of the unquoted `PROGRAM_ARGS` Port of anchore/grype#3738 Signed-off-by: Alex Goodman --- install.sh | 11 +++--- test/install/5_release_script_args_test.sh | 41 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100755 test/install/5_release_script_args_test.sh diff --git a/install.sh b/install.sh index 7fb08d0d4..88303e4f2 100755 --- a/install.sh +++ b/install.sh @@ -8,7 +8,6 @@ REPO="${PROJECT_NAME}" GITHUB_DOWNLOAD_PREFIX=https://github.com/${OWNER}/${REPO}/releases/download INSTALL_SH_BASE_URL=https://get.anchore.io/${PROJECT_NAME} LEGACY_INSTALL_SH_BASE_URL=https://raw.githubusercontent.com/${OWNER}/${PROJECT_NAME} -PROGRAM_ARGS=$@ # signature verification options @@ -791,7 +790,7 @@ prep_signature_verification() { fi } -main() ( +parse_install_args() { # parse arguments # note: never change default install directory (this must always be backwards compatible) @@ -831,6 +830,11 @@ EOF set +u tag=$1 + set -u +} + +main() ( + parse_install_args "$@" if [ -z "${tag}" ]; then log_info "checking github for the current release tag" @@ -838,7 +842,6 @@ EOF else log_info "checking github for release tag='${tag}'" fi - set -u if ! tag=$(get_release_tag "${OWNER}" "${REPO}" "${tag}"); then log_err "unable to find tag='${tag}'" @@ -869,7 +872,7 @@ EOF log_warn "failed to fetch from ${INSTALL_SH_BASE_URL}, trying fallback URL" install_script=$(http_copy "${LEGACY_INSTALL_SH_BASE_URL}/${tag}/install.sh" "") fi - echo "${install_script}" | sh -s -- ${PROGRAM_ARGS} + echo "${install_script}" | sh -s -- "$@" exit $? fi diff --git a/test/install/5_release_script_args_test.sh b/test/install/5_release_script_args_test.sh new file mode 100755 index 000000000..1093b7f66 --- /dev/null +++ b/test/install/5_release_script_args_test.sh @@ -0,0 +1,41 @@ +. test_harness.sh + +# make certain main defers to the (stubbed) tagged release script regardless of the caller's env +DOWNLOAD_TAG_INSTALL_SCRIPT=true + +get_release_tag() { + printf '%s\n' "$3" +} + +prep_signature_verification() { + return 0 +} + +# the "tagged release script" records each argument it receives, one bracketed arg per line +http_copy() { + cat <<'SCRIPT' +printf '[%s]\n' "$@" > "$INSTALL_ARG_CAPTURE" +SCRIPT +} + +test_release_script_receives_original_args() { + test_dir=$(mktemp -d) + INSTALL_ARG_CAPTURE="${test_dir}/actual" + export INSTALL_ARG_CAPTURE + + # note: paths are read here instead of passed to run_test_case, which word-splits its arguments + while IFS= read -r install_path; do + main -b "${install_path}" -d v0.80.0 + + printf '[%s]\n' -b "${install_path}" -d v0.80.0 > "${test_dir}/expected" + assertFilesEqual "${test_dir}/expected" "${INSTALL_ARG_CAPTURE}" "args forwarded to the release script should match the original args (path='${install_path}')" + done <<'PATHS' +/tmp/bin with spaces +/tmp/bin* +/tmp/it's "quoted" +PATHS + + rm -rf -- "${test_dir}" +} + +run_test_case test_release_script_receives_original_args