Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/bin/sh

set -eu

XP_CHANNEL=${XP_CHANNEL:-stable}
XP_VERSION=${XP_VERSION:-current}

os=$(uname -s)
arch=$(uname -m)
OS=${OS:-"${os}"}
ARCH=${ARCH:-"${arch}"}
OS_ARCH=""
COMPRESSED=${COMPRESSED:-"False"}

BIN=${BIN:-crossplane}

# v2.3.0 was the first release from the crossplane/cli repository, whose
# artifacts go to the cli.crossplane.io bucket and uses the binary name
# "crossplane". Use the old releases.crossplane.io hostname and "crank" binary
# for older releases.

url_host="cli.crossplane.io"
bundle_name="crossplane-cli.tar.gz"

if [ "${XP_VERSION}" != "current" ]; then
_ver=$(echo "${XP_VERSION}" | sed 's/^v//' | sed 's/-.*//')
_major=$(echo "${_ver}" | cut -d. -f1)
_minor=$(echo "${_ver}" | cut -d. -f2)

if [ "${_major}" -lt 2 ] 2>/dev/null ||
{ [ "${_major}" -eq 2 ] 2>/dev/null && [ "${_minor}" -lt 3 ] 2>/dev/null; }; then

url_host="releases.crossplane.io"
bundle_name="crank.tar.gz"
BIN="crank"
fi
fi

unsupported_arch() {
os="$1"
arch="$2"
echo "Crossplane does not support $os / $arch at this time."
exit 1
}

case $OS in
CYGWIN* | MINGW64* | Windows*)
if [ "$ARCH" = "x86_64" ]; then
OS_ARCH=windows_amd64
BIN="${BIN}.exe"
else
unsupported_arch "$OS" "$ARCH"
fi
;;
Darwin)
case $ARCH in
x86_64 | amd64)
OS_ARCH=darwin_amd64
;;
arm64)
OS_ARCH=darwin_arm64
;;
*)
unsupported_arch "$OS" "$ARCH"
;;
esac
;;
Linux)
case $ARCH in
x86_64 | amd64)
OS_ARCH=linux_amd64
;;
arm64 | aarch64)
OS_ARCH=linux_arm64
;;
*)
unsupported_arch "$OS" "$ARCH"
;;
esac
;;
*)
unsupported_arch "$OS" "$ARCH"
;;
esac

_compr=$(echo "$COMPRESSED" | tr '[:upper:]' '[:lower:]')

if [ "${_compr}" = "true" ]; then
url_dir="bundle"
url_file="${bundle_name}"
url_error="a compressed file for "
else
url_dir="bin"
url_file="${BIN}"
url_error=""
fi

url="https://${url_host}/${XP_CHANNEL}/${XP_VERSION}/${url_dir}/${OS_ARCH}/${url_file}"

if ! curl -sfL "${url}" -o "${url_file}"; then
echo "Failed to download Crossplane CLI. Please make sure ${url_error}version ${XP_VERSION} exists on channel ${XP_CHANNEL}."
exit 1
fi

if [ "${_compr}" = "true" ]; then
if ! tar xzf "${url_file}"; then
echo "Failed to unpack the Crossplane CLI compressed file."
exit 1
fi
rm "${BIN}.sha256" "${url_file}"
fi
Comment on lines +105 to +111
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix potential failure when .sha256 file is missing from tarball.

Line 110 unconditionally removes ${BIN}.sha256, but with set -e in effect, the script will exit if this file doesn't exist in the extracted tarball. This could break installations if the tarball structure changes.

Additionally, while the script removes the checksum file, it never validates it—a missed security opportunity. Would you like to either:

  1. Add checksum validation before removal, or
  2. Use rm -f to ignore missing files?
🛡️ Proposed fix options

Option 1: Make rm fail-safe (quick fix)

-	rm "${BIN}.sha256" "${url_file}"
+	rm -f "${BIN}.sha256" "${url_file}"

Option 2: Validate checksum before removal (more secure)

+	if [ -f "${BIN}.sha256" ]; then
+		if ! sha256sum -c "${BIN}.sha256"; then
+			echo "Checksum validation failed for Crossplane CLI."
+			exit 1
+		fi
+	fi
 	rm -f "${BIN}.sha256" "${url_file}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ "${_compr}" = "true" ]; then
if ! tar xzf "${url_file}"; then
echo "Failed to unpack the Crossplane CLI compressed file."
exit 1
fi
rm "${BIN}.sha256" "${url_file}"
fi
if [ "${_compr}" = "true" ]; then
if ! tar xzf "${url_file}"; then
echo "Failed to unpack the Crossplane CLI compressed file."
exit 1
fi
rm -f "${BIN}.sha256" "${url_file}"
fi
Suggested change
if [ "${_compr}" = "true" ]; then
if ! tar xzf "${url_file}"; then
echo "Failed to unpack the Crossplane CLI compressed file."
exit 1
fi
rm "${BIN}.sha256" "${url_file}"
fi
if [ "${_compr}" = "true" ]; then
if ! tar xzf "${url_file}"; then
echo "Failed to unpack the Crossplane CLI compressed file."
exit 1
fi
if [ -f "${BIN}.sha256" ]; then
if ! sha256sum -c "${BIN}.sha256"; then
echo "Checksum validation failed for Crossplane CLI."
exit 1
fi
fi
rm -f "${BIN}.sha256" "${url_file}"
fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@install.sh` around lines 105 - 111, The script currently unconditionally runs
rm "${BIN}.sha256" after extracting ${url_file}, which will cause the script to
fail under set -e if the checksum file is absent; either make the removal safe
by using rm -f "${BIN}.sha256" (quick fix) or, preferably, validate the checksum
before deleting by checking for the presence of "${BIN}.sha256", verifying it
with sha256sum -c (or similar) against the extracted binary, fail on mismatch,
and only then remove the checksum file; update the block that handles extraction
of ${url_file} and the subsequent rm to implement one of these two approaches.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we should leave it as it is. If the checksum file is missing from the tarball, then we have a bigger problem to solve. Also, I'd like to introduce the validation functionality in a separate PR

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tampakrap, that's a fair point — failing loudly when .sha256 is absent is actually the safer behavior, since it signals a malformed release artifact rather than silently continuing. Happy to defer the full validation to a separate PR.

Would you like me to open a GitHub issue to track the checksum validation work so it doesn't get lost?

if [ "${BIN}" != "crossplane" ]; then
if ! mv "${BIN}" crossplane; then
echo "Failed to rename the Crossplane CLI binary: \"${BIN}\"."
exit 1
fi
fi

chmod +x crossplane

echo "crossplane CLI downloaded successfully! Run the following commands to finish installing it:"
echo
echo sudo mv crossplane /usr/local/bin
echo crossplane --help
echo
echo "Visit https://crossplane.io to get started. 🚀"
printf "Have a nice day! 👋\n"
5 changes: 5 additions & 0 deletions nix/apps.nix
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@
aws s3 sync --delete --only-show-errors "''${BUILD_PATH}" "''${CHANNEL_PATH}/current"
fi

if [ "''${BRANCH}" == "main" ]; then
echo "Uploading install.sh..."
aws s3 cp --only-show-errors install.sh "s3://crossplane-cli-releases/"
fi

echo "Done"
'';
}
Expand Down
Loading