fix(functions): stop leaking scratch files to trash via bare rm
Verified an agy audit of every bare rm call (the trash-routing C1 shadow) by hand rather than trusting its report. Confirmed correct: scrub.fish's custom_rm strategy and logs.fish's Ctrl-D delete both deliberately want trash for a real, user-facing deletion. Confirmed and fixed three cases where a function's own throwaway scratch file was going to the user's trash instead of being wiped: fc.fish's edited-command tmpfile, dng2avif.fish's intermediate PNM (inconsistent with its own failure-path cleanup two lines up, which already used -f), and _scrollback_prune_junk.fish's junk log files (its sibling _prune_terminal_logs.fish already documents this exact pitfall in its header). Also went further than the report and classified every bypasses-shadow(rm) caller found by grep that had never been audited at all: config-settings.fish and edit.fish (own scratch cleanup, no destructive data at stake) and key-crypt.fish (--remove deletes the user's real input file after encryption, genuinely destructive, already documented in its own header as 'not a secure wipe'). Corrected scrub.fish's tag, which was missing uses-shadow(rm) for its deliberate trash-routing branch alongside the bypass branch it already had tagged. Added a note to the schema doc: rm's flag-based fallback lives inside the shadow itself, so a bare rm -f/rm -rf call is not the caller bypassing anything -- only an explicit command rm/builtin rm earns the tag. This is why dng2avif.fish's fix needed no CLASSIFICATION change: it already used rm -f, which was never actually the bug -- the missing -f on line 122 was.
This commit is contained in:
@@ -72,3 +72,10 @@ schema's own rollout caught several false positives this way: a piped
|
|||||||
`read` misread as an interactive prompt, a documented `--yes` flag missed
|
`read` misread as an interactive prompt, a documented `--yes` flag missed
|
||||||
as an escape hatch, and cleanup of a function's own temp output flagged
|
as an escape hatch, and cleanup of a function's own temp output flagged
|
||||||
as `destructive` despite the explicit exclusion above.
|
as `destructive` despite the explicit exclusion above.
|
||||||
|
|
||||||
|
`rm` specifically has its own internal flag check (any flag other than
|
||||||
|
`-r`/`-R`/`--recursive` falls back to `command rm` *inside the shadow
|
||||||
|
itself*, before it ever touches trash) — a caller writing plain `rm -f`
|
||||||
|
or `rm -rf` is not bypassing anything itself, the shadow is. Only tag
|
||||||
|
`bypasses-shadow(rm)` when the caller explicitly writes `command rm` or
|
||||||
|
`builtin rm`; a bare `rm -f`/`rm -rf` call gets no shadow tag at all.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
# CLASSIFICATION
|
# CLASSIFICATION
|
||||||
# bypasses-shadow(cat)
|
# bypasses-shadow(cat,rm), destructive
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# _scrollback_prune_junk [dir]
|
# _scrollback_prune_junk [dir]
|
||||||
@@ -29,7 +29,7 @@ function _scrollback_prune_junk --description 'Remove empty, trivial, and Kitty
|
|||||||
# Remove any completely empty log file regardless of source
|
# Remove any completely empty log file regardless of source
|
||||||
for f in $dir/*.log $dir/*.txt
|
for f in $dir/*.log $dir/*.txt
|
||||||
test -f $f || continue
|
test -f $f || continue
|
||||||
not test -s $f; and rm $f
|
not test -s $f; and command rm -f $f
|
||||||
end
|
end
|
||||||
|
|
||||||
# Remove any log with only a single meaningful line (e.g. [exited], a lone prompt, or a trivial error)
|
# Remove any log with only a single meaningful line (e.g. [exited], a lone prompt, or a trivial error)
|
||||||
@@ -37,7 +37,7 @@ function _scrollback_prune_junk --description 'Remove empty, trivial, and Kitty
|
|||||||
test -f $f || continue
|
test -f $f || continue
|
||||||
set -l line_count (command cat $f | sed 's/\x1b\[[0-9;:]*[a-zA-Z]//g' | grep -cv '^\s*$')
|
set -l line_count (command cat $f | sed 's/\x1b\[[0-9;:]*[a-zA-Z]//g' | grep -cv '^\s*$')
|
||||||
if test $line_count -le 1
|
if test $line_count -le 1
|
||||||
rm $f
|
command rm -f $f
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ function _scrollback_prune_junk --description 'Remove empty, trivial, and Kitty
|
|||||||
for f in $dir/scrollback_*.log $dir/scrollback_*.txt
|
for f in $dir/scrollback_*.log $dir/scrollback_*.txt
|
||||||
test -f $f || continue
|
test -f $f || continue
|
||||||
if command cat $f | sed 's/\x1b\[[0-9;:]*[a-zA-Z]//g' | grep -q 'Enter the new title for this tab below'
|
if command cat $f | sed 's/\x1b\[[0-9;:]*[a-zA-Z]//g' | grep -q 'Enter the new title for this tab below'
|
||||||
rm $f
|
command rm -f $f
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
# __fish_palette, __config_settings_state, __config_settings_apply,
|
# __fish_palette, __config_settings_state, __config_settings_apply,
|
||||||
# __config_settings_set_value, python3
|
# __config_settings_set_value, python3
|
||||||
#
|
#
|
||||||
|
# CLASSIFICATION
|
||||||
|
# bypasses-shadow(rm)
|
||||||
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# config-settings [-h | --help]
|
# config-settings [-h | --help]
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ function dng2avif --description 'Convert DNG raw to 10-bit HDR AVIF'
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Final Cleanup
|
# Final Cleanup
|
||||||
test -f "$temp_pnm"; and rm "$temp_pnm"
|
test -f "$temp_pnm"; and rm -f "$temp_pnm"
|
||||||
|
|
||||||
set -l size (stat -c '%s' "$output" | numfmt --to=iec)
|
set -l size (stat -c '%s' "$output" | numfmt --to=iec)
|
||||||
echo (set_color yellow)"Complete: $output ($size)"(set_color normal)
|
echo (set_color yellow)"Complete: $output ($size)"(set_color normal)
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
# COMPONENT
|
# COMPONENT
|
||||||
# aliases/dev-tools
|
# aliases/dev-tools
|
||||||
#
|
#
|
||||||
|
# CLASSIFICATION
|
||||||
|
# bypasses-shadow(rm)
|
||||||
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...]
|
# edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...]
|
||||||
#
|
#
|
||||||
|
|||||||
+6
-3
@@ -4,6 +4,9 @@
|
|||||||
# CATEGORY
|
# CATEGORY
|
||||||
# 03-editors-and-viewers
|
# 03-editors-and-viewers
|
||||||
#
|
#
|
||||||
|
# CLASSIFICATION
|
||||||
|
# bypasses-shadow(rm)
|
||||||
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# fc [command_prefix]
|
# fc [command_prefix]
|
||||||
#
|
#
|
||||||
@@ -50,15 +53,15 @@ function fc --description 'Edit and execute the last command (Bash-style fc)'
|
|||||||
# Final check if user cleared the file in the editor
|
# Final check if user cleared the file in the editor
|
||||||
if test -s $tmpfile
|
if test -s $tmpfile
|
||||||
set -l command (cat $tmpfile)
|
set -l command (cat $tmpfile)
|
||||||
rm $tmpfile
|
command rm -f $tmpfile
|
||||||
commandline -r "$command"
|
commandline -r "$command"
|
||||||
commandline -f execute
|
commandline -f execute
|
||||||
else
|
else
|
||||||
rm $tmpfile
|
command rm -f $tmpfile
|
||||||
echo "fc: Aborted (empty file)"
|
echo "fc: Aborted (empty file)"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
rm $tmpfile
|
command rm -f $tmpfile
|
||||||
echo "fc: Could not retrieve history"
|
echo "fc: Could not retrieve history"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
# DEPENDENCIES
|
# DEPENDENCIES
|
||||||
# gpg, tar
|
# gpg, tar
|
||||||
#
|
#
|
||||||
|
# CLASSIFICATION
|
||||||
|
# bypasses-shadow(rm), destructive
|
||||||
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# key-crypt [options] <input> [output]
|
# key-crypt [options] <input> [output]
|
||||||
# key-crypt -i <input> -o <output> [options]
|
# key-crypt -i <input> -o <output> [options]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# 01-file-and-directory
|
# 01-file-and-directory
|
||||||
#
|
#
|
||||||
# CLASSIFICATION
|
# CLASSIFICATION
|
||||||
# bypasses-shadow(rm), destructive
|
# uses-shadow(rm), bypasses-shadow(rm), destructive
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# scrub [-a] [-d] [-h]
|
# scrub [-a] [-d] [-h]
|
||||||
|
|||||||
Reference in New Issue
Block a user