contrib: shell scripts: add quotes around more variables
What changed, and why it matters
This commit adds missing quotation marks around variables in a collection of build and release shell scripts. In shell scripting, unquoted variables can split or be interpreted unexpectedly if paths contain spaces or special characters. The change is defensive hardening of the project's build tooling rather than a fix for a specific reported exploit. It reduces the risk of build failures or accidental command injection during release builds, but it does not patch a vulnerability in the wallet software that end users run.
Treat as low-risk hardening. Reviewers should verify that no unquoted variables remain in the same scripts and that quoting does not break intentional word-splitting elsewhere. No urgent user action is required; downstream builders should update to this commit to reduce build-time fragility.
Security signals we found
shell variable quoting hardening
build/release script hardening
defensive patch against word-splitting and glob expansion
no end-user runtime code changed
Evidence from the diff
The diff hardens 11 shell scripts under contrib/ and the electrum-env wrapper by quoting previously unquoted variable expansions. Affected patterns include directory variables (here, contrib, CONTRIB, VENV_DIR), command substitutions (dirname, realpath), file-name arguments to sha256sum/wget, and the REV/VERSION comparison. Quoting prevents word splitting and glob expansion when values contain whitespace or shell metacharacters. The change is broad but shallow: it does not alter program logic, add input validation, or fix a concrete bug; it is a code-quality/security-hardening sweep.
Changed components
contrib/build-wine/sign.shcontrib/build-wine/unsign.shcontrib/build_tools_util.shcontrib/freeze_containers_distro.shcontrib/freeze_packages.shcontrib/make_libsecp256k1.shcontrib/make_libusb.shcontrib/make_zbar.shcontrib/osx/make_osx.shcontrib/release.shelectrum-envInspect captured patch +27 / −27
diff --git a/contrib/build-wine/sign.sh b/contrib/build-wine/sign.sh
index 51cc244..ecdd305 100755
--- a/contrib/build-wine/sign.sh
+++ b/contrib/build-wine/sign.sh
@@ -2,7 +2,7 @@
set -e
-here=$(dirname "$0")
+here="$(dirname "$0")"
if [ -z "$WIN_SIGNING_PASSWORD" ]; then
echo "password missing"
exit 1
diff --git a/contrib/build-wine/unsign.sh b/contrib/build-wine/unsign.sh
index 380c6ba..3ec2516 100755
--- a/contrib/build-wine/unsign.sh
+++ b/contrib/build-wine/unsign.sh
@@ -5,9 +5,9 @@ set -e
PROJECT_ROOT="$(dirname "$(readlink -e "$0")")/../.."
CONTRIB="$PROJECT_ROOT/contrib"
-here=$(dirname "$0")
+here="$(dirname "$0")"
test -n "$here" -a -d "$here" || exit
-cd $here
+cd "$here"
if ! which osslsigncode > /dev/null 2>&1; then
echo "Please install osslsigncode"
diff --git a/contrib/build_tools_util.sh b/contrib/build_tools_util.sh
index 10adbf7..2dd9b8b 100755
--- a/contrib/build_tools_util.sh
+++ b/contrib/build_tools_util.sh
@@ -35,7 +35,7 @@ function verify_signature() {
function verify_hash() {
local file=$1 expected_hash=$2
- actual_hash=$(sha256sum $file | awk '{print $1}')
+ actual_hash=$(sha256sum "$file" | awk '{print $1}')
if [ "$actual_hash" == "$expected_hash" ]; then
return 0
else
@@ -47,8 +47,8 @@ function verify_hash() {
function download_if_not_exist() {
local file_name=$1 url=$2
- if [ ! -e $file_name ] ; then
- wget -O $file_name "$url"
+ if [ ! -e "$file_name" ] ; then
+ wget -O "$file_name" "$url"
fi
}
diff --git a/contrib/freeze_containers_distro.sh b/contrib/freeze_containers_distro.sh
index f942079..132f817 100755
--- a/contrib/freeze_containers_distro.sh
+++ b/contrib/freeze_containers_distro.sh
@@ -9,7 +9,7 @@ DEBIAN_APPIMAGE_DISTRO="bullseye" # should match build-linux/appimage Dockerfil
DEBIAN_WINE_DISTRO="bookworm" # should match build-wine Dockerfile base
DEBIAN_ANDROID_DISTRO="bookworm" # should match android Dockerfile base
-contrib=$(dirname "$0")
+contrib="$(dirname "$0")"
if [ ! -x /bin/wget ]; then
@@ -17,7 +17,7 @@ if [ ! -x /bin/wget ]; then
exit 1
fi
-DEBIAN_SNAPSHOT_LATEST=$(wget -O- ${DEBIAN_SNAPSHOT_BASE}$(date +"?year=%Y&month=%m") 2>/dev/null | grep "^<a href=\"20" | tail -1 | sed -e 's#[^"]*"\(.\{17,17\}\).*#\1#')
+DEBIAN_SNAPSHOT_LATEST=$(wget -O- "${DEBIAN_SNAPSHOT_BASE}$(date +"?year=%Y&month=%m")" 2>/dev/null | grep "^<a href=\"20" | tail -1 | sed -e 's#[^"]*"\(.\{17,17\}\).*#\1#')
if [ "${DEBIAN_SNAPSHOT_LATEST}x" = "x" ]; then
echo "could not find timestamp for debian packages"
@@ -32,15 +32,15 @@ wget -O /dev/null ${DEBIAN_SNAPSHOT} 2>/dev/null
echo "Valid!"
# build-linux
-echo "deb ${DEBIAN_SNAPSHOT} ${DEBIAN_APPIMAGE_DISTRO} main" >$contrib/build-linux/appimage/apt.sources.list
-echo "deb-src ${DEBIAN_SNAPSHOT} ${DEBIAN_APPIMAGE_DISTRO} main" >>$contrib/build-linux/appimage/apt.sources.list
+echo "deb ${DEBIAN_SNAPSHOT} ${DEBIAN_APPIMAGE_DISTRO} main" > "$contrib/build-linux/appimage/apt.sources.list"
+echo "deb-src ${DEBIAN_SNAPSHOT} ${DEBIAN_APPIMAGE_DISTRO} main" >> "$contrib/build-linux/appimage/apt.sources.list"
# build-wine
-echo "deb ${DEBIAN_SNAPSHOT} ${DEBIAN_WINE_DISTRO} main" >$contrib/build-wine/apt.sources.list
-echo "deb-src ${DEBIAN_SNAPSHOT} ${DEBIAN_WINE_DISTRO} main" >>$contrib/build-wine/apt.sources.list
+echo "deb ${DEBIAN_SNAPSHOT} ${DEBIAN_WINE_DISTRO} main" > "$contrib/build-wine/apt.sources.list"
+echo "deb-src ${DEBIAN_SNAPSHOT} ${DEBIAN_WINE_DISTRO} main" >> "$contrib/build-wine/apt.sources.list"
# android
-echo "deb ${DEBIAN_SNAPSHOT} ${DEBIAN_ANDROID_DISTRO} main" >$contrib/android/apt.sources.list
-echo "deb-src ${DEBIAN_SNAPSHOT} ${DEBIAN_ANDROID_DISTRO} main" >>$contrib/android/apt.sources.list
+echo "deb ${DEBIAN_SNAPSHOT} ${DEBIAN_ANDROID_DISTRO} main" > "$contrib/android/apt.sources.list"
+echo "deb-src ${DEBIAN_SNAPSHOT} ${DEBIAN_ANDROID_DISTRO} main" >> "$contrib/android/apt.sources.list"
echo "updated APT sources to ${DEBIAN_SNAPSHOT}"
diff --git a/contrib/freeze_packages.sh b/contrib/freeze_packages.sh
index e295720..1a5dcc6 100755
--- a/contrib/freeze_packages.sh
+++ b/contrib/freeze_packages.sh
@@ -4,13 +4,13 @@
set -e
venv_dir=~/.electrum-venv
-contrib=$(dirname "$0")
+contrib="$(dirname "$0")"
# note: we should not use a higher version of python than what the binaries bundle
if [[ ! "$SYSTEM_PYTHON" ]] ; then
SYSTEM_PYTHON=$(which python3.10) || printf ""
else
- SYSTEM_PYTHON=$(which $SYSTEM_PYTHON) || printf ""
+ SYSTEM_PYTHON=$(which "$SYSTEM_PYTHON") || printf ""
fi
if [[ ! "$SYSTEM_PYTHON" ]] ; then
echo "Please specify which python to use in \$SYSTEM_PYTHON" && exit 1
@@ -18,15 +18,15 @@ fi
which virtualenv > /dev/null 2>&1 || { echo "Please install virtualenv" && exit 1; }
-${SYSTEM_PYTHON} -m hashin -h > /dev/null 2>&1 || { ${SYSTEM_PYTHON} -m pip install hashin; }
+"${SYSTEM_PYTHON}" -m hashin -h > /dev/null 2>&1 || { "${SYSTEM_PYTHON}" -m pip install hashin; }
for suffix in '' '-hw' '-binaries' '-binaries-mac' '-build-wine' '-build-mac' '-build-base' '-build-appimage' '-build-android'; do
reqfile="requirements${suffix}.txt"
rm -rf "$venv_dir"
- virtualenv -p ${SYSTEM_PYTHON} $venv_dir
+ virtualenv -p "${SYSTEM_PYTHON}" "$venv_dir"
- source $venv_dir/bin/activate
+ source "$venv_dir/bin/activate"
echo "Installing dependencies... (${reqfile})"
@@ -42,7 +42,7 @@ for suffix in '' '-hw' '-binaries' '-binaries-mac' '-build-wine' '-build-mac' '-
requirements=$(pip freeze --all)
- restricted=$(echo $requirements | ${SYSTEM_PYTHON} $contrib/deterministic-build/find_restricted_dependencies.py)
+ restricted=$(echo $requirements | ${SYSTEM_PYTHON} "$contrib/deterministic-build/find_restricted_dependencies.py")
if [ ! -z "$restricted" ]; then
python -m pip install $restricted
requirements=$(pip freeze --all)
diff --git a/contrib/make_libsecp256k1.sh b/contrib/make_libsecp256k1.sh
index 3d8d916..8b194c9 100755
--- a/contrib/make_libsecp256k1.sh
+++ b/contrib/make_libsecp256k1.sh
@@ -21,7 +21,7 @@ LIBSECP_VERSION="a660a4976efe880bae7982ee410b9e0dc59ac983"
set -e
-. $(dirname "$0")/build_tools_util.sh || (echo "Could not source build_tools_util.sh" && exit 1)
+. "$(dirname "$0")/build_tools_util.sh" || (echo "Could not source build_tools_util.sh" && exit 1)
here="$(dirname "$(realpath "$0" 2> /dev/null || grealpath "$0")")"
CONTRIB="$here"
diff --git a/contrib/make_libusb.sh b/contrib/make_libusb.sh
index f796622..4666cae 100755
--- a/contrib/make_libusb.sh
+++ b/contrib/make_libusb.sh
@@ -5,7 +5,7 @@ LIBUSB_VERSION="d52e355daa09f17ce64819122cb067b8a2ee0d4b"
set -e
-. $(dirname "$0")/build_tools_util.sh || (echo "Could not source build_tools_util.sh" && exit 1)
+. "$(dirname "$0")/build_tools_util.sh" || (echo "Could not source build_tools_util.sh" && exit 1)
here="$(dirname "$(realpath "$0" 2> /dev/null || grealpath "$0")")"
CONTRIB="$here"
diff --git a/contrib/make_zbar.sh b/contrib/make_zbar.sh
index e4cd184..e286f30 100755
--- a/contrib/make_zbar.sh
+++ b/contrib/make_zbar.sh
@@ -15,7 +15,7 @@ ZBAR_VERSION="bb05ec54eec57f8397cb13fb9161372a281a1219"
set -e
-. $(dirname "$0")/build_tools_util.sh || (echo "Could not source build_tools_util.sh" && exit 1)
+. "$(dirname "$0")/build_tools_util.sh" || (echo "Could not source build_tools_util.sh" && exit 1)
here="$(dirname "$(realpath "$0" 2> /dev/null || grealpath "$0")")"
CONTRIB="$here"
diff --git a/contrib/osx/make_osx.sh b/contrib/osx/make_osx.sh
index 80dd707..5f20324 100755
--- a/contrib/osx/make_osx.sh
+++ b/contrib/osx/make_osx.sh
@@ -55,8 +55,8 @@ break_legacy_easy_install
# This helps to avoid older versions of pip-installed dependencies interfering with the build.
VENV_DIR="$CONTRIB_OSX/build-venv"
rm -rf "$VENV_DIR"
-python3 -m venv $VENV_DIR
-source $VENV_DIR/bin/activate
+python3 -m venv "$VENV_DIR"
+source "$VENV_DIR/bin/activate"
# don't add debug info to compiled C files (e.g. when pip calls setuptools/wheel calls gcc)
# see https://github.com/pypa/pip/issues/6505#issuecomment-526613584
diff --git a/contrib/release.sh b/contrib/release.sh
index 931fbf1..1119f78 100755
--- a/contrib/release.sh
+++ b/contrib/release.sh
@@ -311,7 +311,7 @@ else
test -f "$PROJECT_ROOT/dist/$apk3" || fail "apk3 not found among built files"
test -f "$PROJECT_ROOT/dist/$dmg" || fail "dmg not found among built files"
- if [ $REV != $VERSION ]; then
+ if [ "$REV" != "$VERSION" ]; then
fail "versions differ, not uploading"
fi
diff --git a/electrum-env b/electrum-env
index a10a698..0cd7436 100755
--- a/electrum-env
+++ b/electrum-env
@@ -13,7 +13,7 @@
set -e
-cd $(dirname $0)
+cd "$(dirname "$0")"
if [ -e ./env/bin/activate ]; then # existing venv
source ./env/bin/activate
else # create new venv
Why this scored 26/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.