Summary
The arcup --self-update command downloads the latest installer directly from the mutable main branch and replaces the local executable without verifying a checksum, commit SHA, or cryptographic signature.
The downloaded file is only checked for an ARCUP_INSTALLER_VERSION declaration. A file containing a higher version string is accepted and copied over the installed arcup executable.
This differs from Arc node release installation, where the archive is verified against a downloaded SHA-256 checksum.
Repository
circlefin/arc-node
Create issue:
https://github.com/circlefin/arc-node/issues/new
Affected file
arcup/arcup
Mutable self-update source:
|
ARCUP_BIN_PATH="$BIN_DIR/arcup" |
|
GITHUB_API_URL="${GITHUB_API_URL:-https://api.github.com}" |
|
case "$GITHUB_API_URL" in |
Self-update implementation:
|
|
|
require_command curl "curl not found. Please install curl." |
|
|
|
_ARCUP_TMP_FILE=$(mktemp) |
|
|
|
info "Downloading latest arcup..." |
|
if ! curl_with_headers -fsSL -o "$_ARCUP_TMP_FILE" "$ARCUP_BIN_URL"; then |
|
error "Failed to download arcup update" |
|
fi |
|
|
|
local remote_version |
|
remote_version=$(grep '^ARCUP_INSTALLER_VERSION=' "$_ARCUP_TMP_FILE" | sed -E 's/ARCUP_INSTALLER_VERSION="(.+)"/\1/') |
|
|
|
if [[ -z "$remote_version" ]]; then |
|
error "Failed to determine remote version" |
|
fi |
|
|
|
if ! version_gt "$remote_version" "$ARCUP_INSTALLER_VERSION"; then |
|
info "Arcup is already up to date (version $ARCUP_INSTALLER_VERSION)" |
|
exit 0 |
|
fi |
|
|
|
info "Updating from $ARCUP_INSTALLER_VERSION to $remote_version..." |
|
if cp "$_ARCUP_TMP_FILE" "$ARCUP_BIN_PATH" 2>/dev/null; then |
|
chmod 755 "$ARCUP_BIN_PATH" |
|
else |
|
error "Failed to update arcup at '$ARCUP_BIN_PATH' — ensure it is writable" |
|
fi |
|
|
|
echo "" |
|
info "Arcup updated successfully to version $remote_version" |
|
exit 0 |
|
} |
|
|
|
# Remove arc binaries and env files |
The update path downloads the script and installs it with:
curl_with_headers -fsSL -o "$_ARCUP_TMP_FILE" "$ARCUP_BIN_URL"
followed by:
cp "$_ARCUP_TMP_FILE" "$ARCUP_BIN_PATH"
chmod 755 "$ARCUP_BIN_PATH"
Steps to reproduce
-
Install an older version of arcup.
-
Run:
-
Observe that the update is downloaded from:
https://raw.githubusercontent.com/circlefin/arc-node/main/arcup/arcup
-
Observe that the downloaded file is only inspected for:
ARCUP_INSTALLER_VERSION="..."
-
No SHA-256 checksum, pinned commit, release asset signature, or trusted signing key is verified before the file replaces the installed executable.
A minimal file containing a higher version declaration and arbitrary shell commands would satisfy the current version check.
Expected behavior
A self-updating executable should verify that the downloaded replacement was published by the Arc maintainers before executing or installing it.
The update should be obtained from an immutable release asset and verified using at least one trusted mechanism, such as:
- a checksum embedded in or anchored by the currently installed updater;
- a cryptographic signature checked against a pinned maintainer key;
- a pinned release commit or immutable GitHub release asset with verified provenance.
Actual behavior
arcup trusts the contents returned from a mutable main branch URL and installs them after checking only that the file declares a newer version.
The existing GPG/checksum verification used for Arc node archives is not applied to the self-update path.
Impact
If the update source or delivery path is compromised, the next user running:
could install and subsequently execute attacker-controlled shell code.
Depending on how Arc operators run the installer, this could expose:
- validator or node host credentials;
- environment variables;
- filesystem contents accessible to the operator;
- node configuration and secrets;
- the integrity of the Arc node installation.
This is particularly sensitive because installer scripts are commonly executed with elevated filesystem permissions.
Suggested fix
Publish arcup as an immutable GitHub release asset and verify it before replacement.
For example:
- Download
arcup, arcup.sha256, and optionally arcup.asc from the same tagged release.
- Verify the checksum.
- Verify the signature against a pinned Arc release-signing fingerprint.
- Validate the downloaded script before replacing the current executable.
- Perform the replacement atomically.
Example flow:
download_file "$tag" "arcup" "$TMP_DIR"
download_file "$tag" "arcup.sha256" "$TMP_DIR"
verify_checksum_file \
"$TMP_DIR/arcup" \
"$TMP_DIR/arcup.sha256" \
"arcup"
install -m 755 "$TMP_DIR/arcup" "$ARCUP_BIN_PATH.new"
mv -f "$ARCUP_BIN_PATH.new" "$ARCUP_BIN_PATH"
The updater should fail closed when verification cannot be completed.
Tests
Add tests confirming that:
- a self-update with a mismatched checksum is rejected;
- an unsigned update is rejected when signatures are required;
- a downloaded file with only a higher version string is insufficient;
- the current executable is preserved when verification fails;
- updates are obtained from an immutable release reference;
- replacement is atomic.
Checklist
Summary
The
arcup --self-updatecommand downloads the latest installer directly from the mutablemainbranch and replaces the local executable without verifying a checksum, commit SHA, or cryptographic signature.The downloaded file is only checked for an
ARCUP_INSTALLER_VERSIONdeclaration. A file containing a higher version string is accepted and copied over the installedarcupexecutable.This differs from Arc node release installation, where the archive is verified against a downloaded SHA-256 checksum.
Repository
circlefin/arc-nodeCreate issue:
https://github.com/circlefin/arc-node/issues/new
Affected file
arcup/arcupMutable self-update source:
arc-node/arcup/arcup
Lines 23 to 25 in 745ba4e
Self-update implementation:
arc-node/arcup/arcup
Lines 435 to 469 in 745ba4e
The update path downloads the script and installs it with:
followed by:
Steps to reproduce
Install an older version of
arcup.Run:
Observe that the update is downloaded from:
Observe that the downloaded file is only inspected for:
ARCUP_INSTALLER_VERSION="..."No SHA-256 checksum, pinned commit, release asset signature, or trusted signing key is verified before the file replaces the installed executable.
A minimal file containing a higher version declaration and arbitrary shell commands would satisfy the current version check.
Expected behavior
A self-updating executable should verify that the downloaded replacement was published by the Arc maintainers before executing or installing it.
The update should be obtained from an immutable release asset and verified using at least one trusted mechanism, such as:
Actual behavior
arcuptrusts the contents returned from a mutablemainbranch URL and installs them after checking only that the file declares a newer version.The existing GPG/checksum verification used for Arc node archives is not applied to the self-update path.
Impact
If the update source or delivery path is compromised, the next user running:
could install and subsequently execute attacker-controlled shell code.
Depending on how Arc operators run the installer, this could expose:
This is particularly sensitive because installer scripts are commonly executed with elevated filesystem permissions.
Suggested fix
Publish
arcupas an immutable GitHub release asset and verify it before replacement.For example:
arcup,arcup.sha256, and optionallyarcup.ascfrom the same tagged release.Example flow:
The updater should fail closed when verification cannot be completed.
Tests
Add tests confirming that:
Checklist