ci: Reject unsafe execution of shell scripts
What changed, and why it matters
This commit adds safety guards to Bitcoin Core's continuous integration (CI) shell scripts. The scripts install software and change system settings, so they could damage a developer's computer or the source code repository if run directly by mistake. The change makes the scripts refuse to run unless a special safety flag, DANGER_RUN_CI_ON_HOST=1, is set, and it arranges for that flag to be set automatically only inside the intended container environment. It is a hardening improvement, not a fix for an active attack.
No urgent action needed. Reviewers and CI users should ensure they only run these scripts through the supported ci_exec path or after explicitly setting DANGER_RUN_CI_ON_HOST=1 in a sandbox. This is a defensive hardening change; consider it for backporting to active release branches that use the same CI scripts.
Security signals we found
Addition of guard condition requiring DANGER_RUN_CI_ON_HOST=1 before destructive CI scripts run
Automatic injection of DANGER_RUN_CI_ON_HOST=1 only inside Docker container execution path
Explicit commit message describing scripts as 'inherently unsafe' and the change as a safety measure
No changes to consensus, networking, wallet, or P2P code
Evidence from the diff
The patch hardens ci/test/01_base_install.sh and ci/test/03_test_script.sh by exiting early unless DANGER_RUN_CI_ON_HOST=1 is set. It also modifies ci/test/02_run_container.py to inject DANGER_RUN_CI_ON_HOST=1 into the Docker container environment, and updates ci/test_imagefile to set the flag when building the sandbox image. This prevents accidental direct execution of destructive CI scripts on a host machine, but it does not address any vulnerability in the Bitcoin Core node software itself.
Changed components
ci/test/01_base_install.shci/test/02_run_container.pyci/test/03_test_script.shci/test_imagefileInspect captured patch +19 / −3
diff --git a/ci/test/01_base_install.sh b/ci/test/01_base_install.sh
index d62221a7..81d6e252 100755
--- a/ci/test/01_base_install.sh
+++ b/ci/test/01_base_install.sh
@@ -8,6 +8,11 @@ export LC_ALL=C.UTF-8
set -o errexit -o pipefail -o xtrace
+if [ "${DANGER_RUN_CI_ON_HOST}" != "1" ]; then
+ echo "This script will make unsafe local and global modifications, so it can only be run inside a container and requires DANGER_RUN_CI_ON_HOST=1"
+ exit 1
+fi
+
CFG_DONE="${BASE_ROOT_DIR}/ci.base-install-done" # Use a global setting to remember whether this script ran to avoid running it twice
if [ "$( cat "${CFG_DONE}" || true )" == "done" ]; then
diff --git a/ci/test/02_run_container.py b/ci/test/02_run_container.py
index dce3730a..abaa5355 100755
--- a/ci/test/02_run_container.py
+++ b/ci/test/02_run_container.py
@@ -158,7 +158,13 @@ def main():
if os.getenv("DANGER_RUN_CI_ON_HOST"):
prefix = []
else:
- prefix = ["docker", "exec", container_id]
+ prefix = [
+ "docker",
+ "exec",
+ "--env",
+ "DANGER_RUN_CI_ON_HOST=1", # Safe to set *inside* the container
+ container_id,
+ ]
return run([*prefix, *cmd_inner], **kwargs)
diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh
index d81bd0b9..d04ff992 100755
--- a/ci/test/03_test_script.sh
+++ b/ci/test/03_test_script.sh
@@ -6,7 +6,12 @@
export LC_ALL=C.UTF-8
-set -ex
+set -o errexit -o xtrace
+
+if [ "${DANGER_RUN_CI_ON_HOST}" != "1" ]; then
+ echo "This script will make unsafe local and global modifications, so it can only be run inside a container and requires DANGER_RUN_CI_ON_HOST=1"
+ exit 1
+fi
cd "${BASE_ROOT_DIR}"
diff --git a/ci/test_imagefile b/ci/test_imagefile
index 93494cc1..908e9a0f 100644
--- a/ci/test_imagefile
+++ b/ci/test_imagefile
@@ -21,4 +21,4 @@ COPY ./ci/test/00_setup_env.sh ./${FILE_ENV} ./ci/test/01_base_install.sh ./ci/t
# Bash is required, so install it when missing
RUN sh -c "bash -c 'true' || ( apk update && apk add --no-cache bash )"
-RUN ["bash", "-c", "cd /ci_container_base/ && set -o errexit && source ./ci/test/00_setup_env.sh && ./ci/test/01_base_install.sh"]
+RUN ["bash", "-c", "cd /ci_container_base/ && set -o errexit && source ./ci/test/00_setup_env.sh && DANGER_RUN_CI_ON_HOST=1 ./ci/test/01_base_install.sh"]
Why this scored 34/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.