fix: harden release validation

This commit is contained in:
proxyctl coordinator
2026-07-17 10:07:46 +08:00
parent 2b161e86e6
commit 65ca1b97cf
5 changed files with 80 additions and 21 deletions
+2 -2
View File
@@ -15,8 +15,8 @@ jobs:
test:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version-file: go.mod
cache: false
+1 -1
View File
@@ -21,7 +21,7 @@ build() {
output="$out/proxyctl-linux-$arch"
(
cd "$repo"
CGO_ENABLED=0 GOOS=linux GOARCH="$arch" \
GOENV=off GOFLAGS= CGO_ENABLED=0 GOOS=linux GOARCH="$arch" \
go build -mod=readonly -buildvcs=false -trimpath \
-ldflags="-s -w -X main.version=$VERSION" \
-o "$output" ./cmd/proxyctl
+19 -9
View File
@@ -5,21 +5,31 @@ repo=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT HUP INT TERM
snapshot_path() {
path=$1
if [ ! -e "$path" ] && [ ! -L "$path" ]; then
printf 'absent\t%s\n' "$path"
return
fi
# Keep traversal, metadata collection, hashing, and sorting as separate
# commands so set -e observes every failure without relying on pipefail.
find -H "$path" -xdev \
-exec stat --printf='metadata\t%F\t%a\t%u\t%g\t%N\n' -- {} + \
>"$work/snapshot-metadata"
LC_ALL=C sort "$work/snapshot-metadata"
find -H "$path" -xdev -type f -exec sha256sum -- {} + \
>"$work/snapshot-content"
LC_ALL=C sort "$work/snapshot-content"
}
snapshot() {
for path in \
"$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.docker/config.json" \
/etc/apt/apt.conf.d /etc/docker/daemon.json /var/lib/proxyctl \
/etc/systemd/system/docker.service.d
do
if [ -d "$path" ]; then
find "$path" -type f -print0 2>/dev/null | sort -z | xargs -0 -r sha256sum 2>/dev/null || ls -ld "$path"
elif [ -r "$path" ]; then
sha256sum "$path"
elif [ -e "$path" ]; then
ls -ld "$path"
else
printf 'absent %s\n' "$path"
fi
snapshot_path "$path"
done
if command -v gsettings >/dev/null 2>&1; then
gsettings list-recursively org.gnome.system.proxy 2>&1 || true
+37
View File
@@ -5,15 +5,52 @@ repo=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT HUP INT TERM
assert_no_process_test_seam() {
artifact=$1
if LC_ALL=C grep -a -F \
-e 'proxyctl_process_test' \
-e 'PROXYCTL_PROCESS_TEST_HOME' \
"$artifact" >/dev/null
then
printf 'release artifact contains the process-test seam: %s\n' "$artifact" >&2
return 1
fi
}
VERSION=v1.0.0 "$repo/scripts/build-release.sh" "$work/first"
VERSION=v1.0.0 "$repo/scripts/build-release.sh" "$work/second"
GOFLAGS='-tags=proxyctl_process_test' \
VERSION=v1.0.0 "$repo/scripts/build-release.sh" "$work/malicious-goflags"
printf 'GOFLAGS=-tags=proxyctl_process_test\n' >"$work/malicious-goenv"
GOENV="$work/malicious-goenv" \
VERSION=v1.0.0 "$repo/scripts/build-release.sh" "$work/malicious-goenv-build"
for arch in amd64 arm64; do
binary="proxyctl-linux-$arch"
test -x "$work/first/$binary"
cmp "$work/first/$binary" "$work/second/$binary"
cmp "$work/first/$binary" "$work/malicious-goflags/$binary"
cmp "$work/first/$binary" "$work/malicious-goenv-build/$binary"
assert_no_process_test_seam "$work/first/$binary"
assert_no_process_test_seam "$work/malicious-goflags/$binary"
assert_no_process_test_seam "$work/malicious-goenv-build/$binary"
done
cmp "$work/first/SHA256SUMS" "$work/second/SHA256SUMS"
cmp "$work/first/SHA256SUMS" "$work/malicious-goflags/SHA256SUMS"
cmp "$work/first/SHA256SUMS" "$work/malicious-goenv-build/SHA256SUMS"
(
cd "$repo"
GOENV=off GOFLAGS= CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -mod=readonly -buildvcs=false -trimpath \
-tags=proxyctl_process_test -o "$work/known-contaminated" ./cmd/proxyctl
)
if assert_no_process_test_seam "$work/known-contaminated"; then
echo 'release artifact validation accepted a known contaminated binary' >&2
exit 1
fi
printf 'process-test seam scan rejected a known contaminated binary\n'
(
cd "$work/first"
sha256sum -c SHA256SUMS
+21 -9
View File
@@ -10,19 +10,31 @@ state="$work/state"
bin="$work/bin"
mkdir -p "$home" "$config" "$state" "$bin"
snapshot_host_path() {
path=$1
if [ ! -e "$path" ] && [ ! -L "$path" ]; then
printf 'absent\t%s\n' "$path"
return
fi
# Avoid pipelines: traversal, stat, hash, and sort failures must stop the
# verification rather than being mistaken for an unchanged host snapshot.
find -H "$path" -xdev \
-exec stat --printf='metadata\t%F\t%a\t%u\t%g\t%N\n' -- {} + \
>"$work/host-snapshot-metadata"
LC_ALL=C sort "$work/host-snapshot-metadata"
find -H "$path" -xdev -type f -exec sha256sum -- {} + \
>"$work/host-snapshot-content"
LC_ALL=C sort "$work/host-snapshot-content"
}
snapshot_host() {
for path in \
"$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.docker/config.json" \
/etc/apt/apt.conf.d/99proxyctl /etc/docker/daemon.json \
/var/lib/proxyctl/docker-daemon.json
/etc/apt/apt.conf.d /etc/docker/daemon.json /var/lib/proxyctl \
/etc/systemd/system/docker.service.d
do
if [ -r "$path" ]; then
sha256sum "$path"
elif [ -e "$path" ]; then
ls -ld "$path"
else
printf 'absent %s\n' "$path"
fi
snapshot_host_path "$path"
done
if command -v gsettings >/dev/null 2>&1; then
gsettings get org.gnome.system.proxy mode 2>&1 || true