Fix: Close runtime provenance residuals
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user