Fix: Close runtime provenance residuals

This commit is contained in:
Gabriel Brown
2026-08-27 09:22:17 -04:00
parent 31fc1d3eaa
commit 92c60c3ecd
2 changed files with 190 additions and 16 deletions
+36 -11
View File
@@ -139,25 +139,48 @@ _archive_member_is_safe() {
|| "$member" == "$expected_top/"* ]]
}
_bun_zip_entry_types_match() {
local archive="$1" archive_top="$2" details entry_types
details="$(unzip -Z -s "$archive")" || return 1
entry_types="$(awk -v directory="$archive_top/" -v binary="$archive_top/bun" '
$NF == directory || $NF == binary { print substr($1, 1, 1), $NF }
' <<<"$details")" || return 1
[[ "$entry_types" == "d $archive_top/"$'\n'"- $archive_top/bun" ]]
}
_tree_links_stay_inside() {
local root="$1" link resolved
while IFS= read -r -d '' link; do
resolved="$(realpath -m -- "$link")" || return 1
[[ "$resolved" == "$root" || "$resolved" == "$root/"* ]] || return 1
done < <(find "$root" -type l -print0)
local root="$1" link resolved scan_fd scan_pid scan_status=0 invalid=0
# Retain and wait for find's PID: a loop fed directly by process substitution
# cannot otherwise distinguish an empty tree from a failed traversal.
exec {scan_fd}< <(find "$root" -type l -print0)
scan_pid=$!
while IFS= read -r -d '' link <&"$scan_fd"; do
resolved="$(realpath -m -- "$link")" || { invalid=1; continue; }
[[ "$resolved" == "$root" || "$resolved" == "$root/"* ]] || invalid=1
done
exec {scan_fd}<&-
wait "$scan_pid" || scan_status=$?
(( scan_status == 0 && invalid == 0 ))
}
_tree_hardlinks_stay_inside() {
local root="$1" device inode link_count key
local root="$1" device inode link_count key scan_fd scan_pid scan_status=0
local invalid=0
local -A names_in_tree=() inode_links=()
while read -r device inode link_count; do
exec {scan_fd}< <(find "$root" -type f -printf '%D %i %n\n')
scan_pid=$!
while read -r device inode link_count <&"$scan_fd"; do
key="$device:$inode"
names_in_tree["$key"]=$(( ${names_in_tree[$key]:-0} + 1 ))
inode_links["$key"]="$link_count"
done < <(find "$root" -type f -printf '%D %i %n\n')
for key in "${!names_in_tree[@]}"; do
[[ "${names_in_tree[$key]}" == "${inode_links[$key]}" ]] || return 1
done
exec {scan_fd}<&-
wait "$scan_pid" || scan_status=$?
(( scan_status == 0 )) || return 1
for key in "${!names_in_tree[@]}"; do
[[ "${names_in_tree[$key]}" == "${inode_links[$key]}" ]] || invalid=1
done
(( invalid == 0 ))
}
_atomic_symlink() (
@@ -348,6 +371,8 @@ _install_bun() (
listing="$(unzip -Z1 "$archive")" || { rm -rf -- "$stage"; return 1; }
[[ "$listing" == "$archive_top/"$'\n'"$archive_top/bun" ]] \
|| { rm -rf -- "$stage"; return 1; }
_bun_zip_entry_types_match "$archive" "$archive_top" \
|| { rm -rf -- "$stage"; return 1; }
while IFS= read -r member; do
_archive_member_is_safe "$member" "$archive_top" \
|| { rm -rf -- "$stage"; return 1; }
@@ -1064,7 +1089,7 @@ _install_claude_code() {
"$staged_repo" /etc/yum.repos.d/claude-code.repo || status=$?
if (( status == 0 )); then
sudo dnf install -y --repo=claude-code --repo=fedora --repo=updates \
claude-code || status=$?
--from-repo=claude-code claude-code || status=$?
fi
rm -rf -- "$work"
return "$status"