fix(skill-stocktake): use NUL-delimited paths to avoid newline desync

The find -> sort -> read chain in both scripts used newline-delimited
records (plain read -r), so a skill directory name containing a
literal newline would be split across two records. Verified with a
directory literally named "evil\nskill": the old reader produced a
truncated "evil" fragment plus an orphan "skill/SKILL.md" fragment,
inflating the skill count and throwing awk/date errors on the garbage
paths.

Switch to -print0 / sort -z / read -r -d '' in both scripts so a path
is always read as a single record, regardless of its contents. Paths
under scan are untrusted input.

Addresses further CodeRabbit review feedback on PR #2640.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FhDjpSfrbPpnpqT3CZBEX1
This commit is contained in:
Deepu S Nath
2026-08-29 14:55:13 -04:00
committed by haelyra
co-authored by Claude Sonnet 5
parent dfb5da59fb
commit 981f97bff4
2 changed files with 10 additions and 6 deletions
+5 -3
View File
@@ -56,13 +56,15 @@ process_dir() {
# Capture find's exit status and stderr instead of discarding them: with -L,
# a broken symlink or unreadable directory makes find skip that entry AND
# exit non-zero, which would otherwise silently under-count skills.
if ! find -L "$dir" -name "SKILL.md" -type f >"$find_out" 2>"$find_err"; then
# NUL-delimited (-print0 / sort -z / read -d '') so a path containing a
# literal newline can't desync record boundaries — paths here are untrusted.
if ! find -L "$dir" -name "SKILL.md" -type f -print0 >"$find_out" 2>"$find_err"; then
echo "Warning: find encountered errors while scanning $dir (broken symlinks or permission issues may cause skills to be missed):" >&2
cat "$find_err" >&2
fi
sort -o "$find_out" "$find_out"
sort -z -o "$find_out" "$find_out"
while IFS= read -r file; do
while IFS= read -r -d '' file; do
local mtime dp is_new
mtime=$(date -u -r "$file" +%Y-%m-%dT%H:%M:%SZ)
dp="${file/#$HOME/~}"
+5 -3
View File
@@ -100,13 +100,15 @@ scan_dir_to_json() {
# Capture find's exit status and stderr instead of discarding them: with -L,
# a broken symlink or unreadable directory makes find skip that entry AND
# exit non-zero, which would otherwise silently under-count skills.
if ! find -L "$dir" -name "SKILL.md" -type f >"$find_out" 2>"$find_err"; then
# NUL-delimited (-print0 / sort -z / read -d '') so a path containing a
# literal newline can't desync record boundaries — paths here are untrusted.
if ! find -L "$dir" -name "SKILL.md" -type f -print0 >"$find_out" 2>"$find_err"; then
echo "Warning: find encountered errors while scanning $dir (broken symlinks or permission issues may cause skills to be missed):" >&2
cat "$find_err" >&2
fi
sort -o "$find_out" "$find_out"
sort -z -o "$find_out" "$find_out"
while IFS= read -r file; do
while IFS= read -r -d '' file; do
local name desc mtime u7 u30 dp
name=$(extract_field "$file" "name")
desc=$(extract_field "$file" "description")