#!/usr/bin/env bash set -uo pipefail # CASAN Plan-16 SEC-20 (ARCH-04 / ARCH-09) — verify the required toolchain. # # Gate verdicts depend on external binaries (python/openssl/grep/sha256sum...). If # one is MISSING the control can silently no-op (ARCH-09); if one is PATH-SHADOWED # by an attacker-planted copy (ARCH-04, e.g. a fake `grep` that always matches # nothing) the attacker controls the verdict. This fails CLOSED: # * a required tool that is not found -> refuse, # * a tool resolving INSIDE the workspace / cwd -> refuse (planted binary), # * with CASAN_TOOLCHAIN_TRUSTED_DIRS set, a tool outside those dirs -> refuse. # # Usage: toolchain-verify.sh [tool ...] (default: python3 openssl grep awk sed) # Env: CASAN_TOOLCHAIN_TRUSTED_DIRS=/usr/bin:/bin:... (opt-in allowlist; prod sets it) # Exit: 0 ok, 1 missing/shadowed/untrusted. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/casan-paths.sh" PROJECT_ROOT="$CASAN_APP_ROOT" REQUIRED=("$@") if [[ ${#REQUIRED[@]} -eq 0 ]]; then REQUIRED=(python3 openssl grep awk sed) fi IFS=':' read -r -a TRUSTED <<< "${CASAN_TOOLCHAIN_TRUSTED_DIRS:-}" fail=0 for tool in "${REQUIRED[@]}"; do path="$(command -v "$tool" 2>/dev/null || true)" if [[ -z "$path" ]]; then echo "TOOLCHAIN_MISSING tool=$tool (fail-closed)" >&2 fail=1; continue fi # Resolve to a real, absolute path (follow the symlink dir). dir="$(cd "$(dirname "$path")" 2>/dev/null && pwd -P || echo "")" real="$dir/$(basename "$path")" # A required tool resolving inside the repo / cwd is a planted-binary red flag. case "$real" in "$PROJECT_ROOT"/*|"$PWD"/*|./*) echo "TOOLCHAIN_SHADOWED tool=$tool path=$real (fail-closed)" >&2 fail=1; continue ;; esac # Opt-in allowlist: in prod the tool MUST live under a trusted system dir. if [[ -n "${CASAN_TOOLCHAIN_TRUSTED_DIRS:-}" ]]; then ok=0 for pfx in "${TRUSTED[@]}"; do [[ -n "$pfx" ]] || continue case "$real" in "$pfx"/*) ok=1; break ;; esac done if [[ "$ok" -ne 1 ]]; then echo "TOOLCHAIN_UNTRUSTED_PATH tool=$tool path=$real (not under CASAN_TOOLCHAIN_TRUSTED_DIRS)" >&2 fail=1 fi fi done if [[ "$fail" -eq 0 ]]; then echo "TOOLCHAIN_OK tools=${#REQUIRED[@]}" exit 0 fi exit 1