Skip to content

Commit 1c303c7

Browse files
oharboeclaude
andcommitted
bazel-hermetic: tolerate custom bazel wrappers; pure-bash env lookup; require HOME
Three findings from the latest Gemini pass, all on etc/bazel-hermetic: - Custom (non-bazelisk) bazel wrappers no longer hard-fail. A wrapper script starts with #!, so it entered the bazelisk-resolution block and then exited 1 when no bazelisk-managed binary was found under the cache. Now it warns and uses the wrapper directly; if the wrapper's interpreter is not on the pruned PATH the launch fails on its own, which beats refusing to run for everyone with a custom wrapper. (That error path was in fact unreachable before: the failing `cat "${meta}"` aborted the `real=` assignment under set -e; guarded with `|| true`.) - Environment preservation uses a pure-bash `eval "value=\${$var:-}"` instead of `printenv "$var"`: no subprocess per variable, and no silent loss of proxy/SSH/TLS vars if printenv is off PATH. Names come from the fixed list, never input, so eval is not an injection surface. Still bash-3.2-safe (no ${!var}/-v). - HOME uses ${HOME:?...}: fail early with a clear message if HOME is unset/empty (bazel needs it for caches and user bazelrc) rather than passing an empty HOME. Also satisfies the earlier set -u concern. Re-verified with the stub-bazel harness: normal ELF path, the bug/info paths, an empty-HOME early exit, and a non-bazelisk shebang wrapper now warning and running. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
1 parent 8616be0 commit 1c303c7

1 file changed

Lines changed: 25 additions & 12 deletions

File tree

etc/bazel-hermetic

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,21 @@ if [[ ${BAZEL} == *bazelisk* || $(head -c 2 < "${BAZEL}") == '#!' ]]; then
109109
bazelisk_home=${HOME}/.cache/bazelisk
110110
fi
111111
meta="${bazelisk_home}/downloads/metadata/bazelbuild/bazel-${version}-${os}-${arch}"
112-
real="${bazelisk_home}/downloads/sha256/$(cat "${meta}" 2>/dev/null)/bin/bazel"
113-
[[ -x ${real} ]] ||
114-
{ echo >&2 "bazel-hermetic: ${BAZEL} is a wrapper and no real bazel-${version} found under ${bazelisk_home}"; exit 1; }
115-
BAZEL=${real}
112+
# || true: a missing metadata file (non-bazelisk wrapper) must fall
113+
# through to the check below, not abort the assignment under set -e.
114+
real="${bazelisk_home}/downloads/sha256/$(cat "${meta}" 2>/dev/null || true)/bin/bazel"
115+
if [[ -x ${real} ]]; then
116+
BAZEL=${real}
117+
else
118+
# A wrapper we can't resolve to a bazelisk-managed binary — e.g. a
119+
# custom (non-bazelisk) bazel wrapper. Use it directly rather than
120+
# refusing to run: if its interpreter isn't on the pruned PATH the
121+
# launch fails loudly on its own, which is better than blocking every
122+
# non-bazelisk wrapper up front.
123+
echo >&2 "etc/bazel-hermetic: ${BAZEL} looks like a wrapper but no" \
124+
"bazelisk-managed bazel-${version} was found under" \
125+
"${bazelisk_home}; using it directly"
126+
fi
116127
fi
117128
ln -sfn "${BAZEL}" "${TOOLBOX}/bazel"
118129

@@ -172,12 +183,12 @@ preserved_env=()
172183
for var in http_proxy https_proxy no_proxy HTTP_PROXY HTTPS_PROXY NO_PROXY \
173184
SSH_AUTH_SOCK SSL_CERT_FILE SSL_CERT_DIR XDG_CACHE_HOME TMPDIR \
174185
DISPLAY WAYLAND_DISPLAY XAUTHORITY; do
175-
# printenv, not ${!var} or -v: these run before the pruned exec, so keep
176-
# them portable to the bash 3.2 that macOS ships as /bin/bash. -v needs
177-
# bash 4.2, and indirect expansion composed with a modifier (${!var:-})
178-
# is unreliable on 3.2. All of these are exported environment variables,
179-
# so printenv reads them directly and set -u never sees an unset name.
180-
value=$(printenv "${var}" || true)
186+
# Pure-bash lookup via eval: no subprocess (vs printenv, which also
187+
# silently drops everything if it isn't on PATH), and no ${!var}/-v,
188+
# which are unreliable on the bash 3.2 macOS ships. The names come from
189+
# the fixed list above, never from input, so the eval is not an
190+
# injection surface. ${var:-} keeps set -u quiet when the var is unset.
191+
eval "value=\${${var}:-}"
181192
if [[ -n ${value} ]]; then
182193
preserved_env+=("${var}=${value}")
183194
fi
@@ -206,9 +217,11 @@ case "$(uname -s)" in
206217
*) lang=C.UTF-8 ;;
207218
esac
208219

209-
# HOME:- and the array guards: same set -u / bash 3.2 safety as above.
220+
# HOME:? fails early with a clear message if HOME is unset/empty (bazel
221+
# needs it for its caches and user bazelrc) instead of silently passing
222+
# an empty HOME; the array guards give the set -u / bash 3.2 safety.
210223
exec env -i \
211-
HOME="${HOME:-}" \
224+
HOME="${HOME:?etc/bazel-hermetic: HOME must be set}" \
212225
USER="${USER:-$(id -un)}" \
213226
LOGNAME="${LOGNAME:-$(id -un)}" \
214227
TERM="${TERM:-dumb}" \

0 commit comments

Comments
 (0)