Skip to content

Commit 66701f6

Browse files
committed
[Change] coreutils: command cat prefix across 26 bare cat sites — el6 PATH portability
Project Shell Standards (parent CLAUDE.md) require `command` prefix on all coreutils in project source to resolve via PATH for portability across pre-usr-merge distros (CentOS 6 has /bin/cat, not /usr/bin/cat). This commit closes the bare-`cat` advisory item carried in MEMORY since 2026-04-06. 26 sites across 11 files: files/internals/lmd_alert.sh 7 sites files/internals/lmd_sigs.sh 7 sites files/internals/lmd_session.sh 8 sites files/internals/lmd_monitor.sh 4 sites files/internals/lmd_quarantine.sh 4 sites files/internals/lmd_scan.sh 3 sites files/internals/lmd_update.sh 4 sites files/internals/lmd_engine.sh 1 site files/internals/lmd_config.sh 1 site files/maldet 1 site install.sh 1 site Forms covered: anchored `cat "$f" > "$o"` (statement-level), `$(cat "$f")` (subshell capture), `$(cat "$f" 2>/dev/null)` (suppression-wrapped), `&& cat "$f" >> "$o"` (mid-line after &&), heredoc-substitution `$(cat "$f")` (inside double-quoted strings). Word-boundary grep `\bcat\b | grep -v 'command cat'` now empty across LMD source — only `files/maldet:240 cat<<EOF` remains, which is the heredoc form exempt by project rule and project verification grep (`^\s*cat\s(?!<<)`). Vendored libraries (alert_lib.sh:309, tlog_lib.sh:441) unchanged — fix upstream, not in-tree. No functional change; bash -n passes across all touched files.
1 parent 8c1c58a commit 66701f6

13 files changed

Lines changed: 56 additions & 44 deletions

CHANGELOG

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ v2.0.2 | May 12 2026:
2727
as the earlier comment-discipline commit cdd0814); closes the
2828
attacker-writable manifest vector against root-startup invocation
2929
of pkg_fhs_verify_farm from files/maldet:78
30+
[Change] coreutils: `command cat` prefix on 26 bare `cat` sites across 9
31+
files (lmd_alert, lmd_config, lmd_engine, lmd_monitor, lmd_quarantine,
32+
lmd_scan, lmd_session, lmd_sigs, lmd_update, files/maldet, install.sh)
33+
— el6 PATH portability per project Shell Standards; closes the
34+
advisory item carried in MEMORY since 2026-04-06. Heredoc form
35+
(`cat<<EOF`) and vendored libraries (alert_lib, tlog_lib) unchanged
3036

3137
-- Bug Fixes --
3238

CHANGELOG.RELEASE

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ v2.0.2 | May 12 2026:
2727
as the earlier comment-discipline commit cdd0814); closes the
2828
attacker-writable manifest vector against root-startup invocation
2929
of pkg_fhs_verify_farm from files/maldet:78
30+
[Change] coreutils: `command cat` prefix on 26 bare `cat` sites across 9
31+
files (lmd_alert, lmd_config, lmd_engine, lmd_monitor, lmd_quarantine,
32+
lmd_scan, lmd_session, lmd_sigs, lmd_update, files/maldet, install.sh)
33+
— el6 PATH portability per project Shell Standards; closes the
34+
advisory item carried in MEMORY since 2026-04-06. Heredoc form
35+
(`cat<<EOF`) and vendored libraries (alert_lib, tlog_lib) unchanged
3036

3137
-- Bug Fixes --
3238

files/internals/lmd_alert.sh

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,10 @@ To enable, set <code style=\"font-family:'Courier New',Courier,monospace;font-si
164164
fi
165165
if [ -f "$_clist" ]; then
166166
CLEANED_SECTION_TEXT="CLEANED & RESTORED FILES:
167-
$(cat "$_clist")
167+
$(command cat "$_clist")
168168
"
169169
local _clist_html
170-
_clist_html=$(_alert_html_escape "$(cat "$_clist")")
170+
_clist_html=$(_alert_html_escape "$(command cat "$_clist")")
171171
CLEANED_SECTION_HTML="<table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" style=\"margin-bottom:12px;\">
172172
<tr><td style=\"color:#71717a;font-size:12px;text-transform:uppercase;letter-spacing:1px;padding-bottom:6px;\">Cleaned &amp; Restored Files</td></tr>
173173
<tr><td style=\"font-family:'Courier New',Courier,monospace;font-size:12px;color:#09090b;background-color:#f4f4f5;padding:8px 12px;border-radius:4px;border:1px solid #d4d4d8;word-break:break-all;\">${_clist_html//$'\n'/<br>}</td></tr></table>"
@@ -186,10 +186,10 @@ $(cat "$_clist")
186186
fi
187187
if [ -f "$_slist" ]; then
188188
SUSPENDED_SECTION_TEXT="SUSPENDED ACCOUNTS:
189-
$(cat "$_slist")
189+
$(command cat "$_slist")
190190
"
191191
local _slist_html
192-
_slist_html=$(_alert_html_escape "$(cat "$_slist")")
192+
_slist_html=$(_alert_html_escape "$(command cat "$_slist")")
193193
SUSPENDED_SECTION_HTML="<table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" style=\"margin-bottom:12px;\">
194194
<tr><td style=\"color:#71717a;font-size:12px;text-transform:uppercase;letter-spacing:1px;padding-bottom:6px;\">Suspended Accounts</td></tr>
195195
<tr><td style=\"font-family:'Courier New',Courier,monospace;font-size:12px;color:#09090b;background-color:#f4f4f5;padding:8px 12px;border-radius:4px;border:1px solid #d4d4d8;\">${_slist_html//$'\n'/<br>}</td></tr></table>"
@@ -1222,7 +1222,7 @@ trim_log() {
12221222
local tmplog
12231223
tmplog=$(mktemp "${log}.trim.XXXXXX")
12241224
tail -n +"$((trim + 1))" "$log" > "$tmplog" 2>/dev/null
1225-
cat "$tmplog" > "$log" 2>/dev/null
1225+
command cat "$tmplog" > "$log" 2>/dev/null
12261226
command rm -f "$tmplog"
12271227
fi
12281228
elif [ ! -f "$log" ] && [ "$3" == "1" ]; then
@@ -1566,7 +1566,7 @@ _genalert_digest() {
15661566

15671567
# Monitor tlog sources — only read when monitor session is active
15681568
if [ "$_has_monitor" -eq 1 ]; then
1569-
scan_session=$(cat "$sessdir/session.monitor.current")
1569+
scan_session=$(command cat "$sessdir/session.monitor.current")
15701570
tlog_read "$scan_session" "digest.alert" "$tmpdir" "lines" > "$tmpdir/.digest.alert.hits"
15711571
tlog_read "$clean_history" "digest.clean.alert" "$tmpdir" "lines" > "$tmpdir/.digest.clean.hits"
15721572
tlog_read "$monitor_scanned_history" "digest.monitor.alert" "$tmpdir" "lines" > "$tmpdir/.digest.monitor.alert"
@@ -1861,7 +1861,7 @@ _test_alert_digest() {
18611861
local _had_cursor=0 _cursor_backup=""
18621862
if [ -f "$_cursor_file" ]; then
18631863
_had_cursor=1
1864-
_cursor_backup=$(cat "$_cursor_file")
1864+
_cursor_backup=$(command cat "$_cursor_file")
18651865
fi
18661866

18671867
local _now

files/internals/lmd_config.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ import_conf() {
377377
import_config_expire=43200
378378
fi
379379
if [ -f "$sessdir/.import_conf.utime" ]; then
380-
import_utime=$(cat "$sessdir/.import_conf.utime")
380+
import_utime=$(command cat "$sessdir/.import_conf.utime")
381381
if [ -z "$import_utime" ]; then
382382
import_utime="0"
383383
fi

files/internals/lmd_engine.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ _hex_csig_batch_worker() {
473473
if [ -n "${_uni_sids[$_elem]:-}" ]; then
474474
seq 1 "$_total_files"
475475
elif [ -s "${_match_dir}/${_elem}" ]; then
476-
cat "${_match_dir}/${_elem}"
476+
command cat "${_match_dir}/${_elem}"
477477
fi
478478
done | sort -n | uniq -c | awk -v thresh="$_threshold" \
479479
'$1 >= thresh {print $2}' > "$_or_merge"

files/internals/lmd_monitor.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ _monitor_cycle_tick() {
440440
fi
441441

442442
# Record scanned files in monitor history
443-
cat "$_filtered_list" >> "$monitor_scanned_history" 2>/dev/null # safe: file may not exist yet
443+
command cat "$_filtered_list" >> "$monitor_scanned_history" 2>/dev/null # safe: file may not exist yet
444444

445445
# Count per-cycle hits (delta since pre-scan snapshot)
446446
local _post_scan_lines _cycle_hits
@@ -468,7 +468,7 @@ monitor_kill() {
468468
# Called by maldet -k/--kill-monitor.
469469
local _pid
470470
if [ -f "$tmpdir/monitor.pid" ]; then
471-
_pid=$(cat "$tmpdir/monitor.pid")
471+
_pid=$(command cat "$tmpdir/monitor.pid")
472472
fi
473473
if [ -z "$_pid" ] || ! kill -0 "$_pid" 2>/dev/null; then
474474
# Fallback: find by inotifywait process (old-style)
@@ -524,7 +524,7 @@ monitor_init() {
524524
# Check for existing monitor
525525
if [ -f "$tmpdir/monitor.pid" ]; then
526526
local _existing_pid
527-
_existing_pid=$(cat "$tmpdir/monitor.pid")
527+
_existing_pid=$(command cat "$tmpdir/monitor.pid")
528528
if [ -n "$_existing_pid" ] && kill -0 "$_existing_pid" 2>/dev/null; then
529529
eout "{mon} existing monitor process detected (pid: $_existing_pid, try -k)" 1
530530
exit 1
@@ -544,8 +544,8 @@ monitor_init() {
544544
# Kernel tuning
545545
if [ -f "/proc/sys/fs/inotify/max_user_instances" ] && [ -f "/proc/sys/fs/inotify/max_user_watches" ]; then
546546
local cur_user_watches cur_user_instances users_tot inotify_user_watches
547-
cur_user_watches=$(cat /proc/sys/fs/inotify/max_user_watches)
548-
cur_user_instances=$(cat /proc/sys/fs/inotify/max_user_instances)
547+
cur_user_watches=$(command cat /proc/sys/fs/inotify/max_user_watches)
548+
cur_user_instances=$(command cat /proc/sys/fs/inotify/max_user_instances)
549549
users_tot=$(awk -F: -v min="$inotify_minuid" '$3 >= min {n++} END {print n+0}' /etc/passwd)
550550
inotify_user_watches=$((inotify_base_watches * users_tot))
551551
if [ "$cur_user_instances" -lt "$inotify_user_instances" ]; then

files/internals/lmd_quarantine.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -561,9 +561,9 @@ _batch_record_hits() {
561561
}' "$_enriched" > "$_sess_block"
562562

563563
# Append in bulk writes
564-
cat "$_hist_block" >> "$hits_history"
564+
command cat "$_hist_block" >> "$hits_history"
565565
if [ -n "$scan_session" ]; then
566-
cat "$_sess_block" >> "$scan_session"
566+
command cat "$_sess_block" >> "$scan_session"
567567
fi
568568

569569
# Summary eout — one line instead of N
@@ -690,7 +690,7 @@ _batch_quarantine() {
690690
fi
691691

692692
# Update quarantine history and scan_session (overwrite non-quarantine entries)
693-
cat "$_quar_hist_block" >> "$quar_history"
693+
command cat "$_quar_hist_block" >> "$quar_history"
694694

695695
# Update scan_session: set field 3 (quarpath) for quarantined files.
696696
# Build lookup from _quar_sess_block (only successfully quarantined files),
@@ -705,7 +705,7 @@ _batch_quarantine() {
705705
/^#/ { print; next }
706706
{ if ($2 in quar) $3 = quar[$2]; print }
707707
' "$_quar_lookup" "$scan_session" > "$_updated_sess"
708-
cat "$_updated_sess" > "$scan_session"
708+
command cat "$_updated_sess" > "$scan_session"
709709
command rm -f "$_quar_lookup" "$_updated_sess"
710710
fi
711711

files/internals/lmd_scan.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ _wait_workers_with_progress() {
335335
if [ -d "$_progress_dir" ]; then
336336
for _wpath in "$_progress_dir"/*; do
337337
if [ -f "$_wpath" ]; then
338-
_wval=$(cat "$_wpath" 2>/dev/null)
338+
_wval=$(command cat "$_wpath" 2>/dev/null)
339339
if [ -n "$_wval" ] && [ "$_wval" -gt 0 ] 2>/dev/null; then
340340
_processed=$((_processed + _wval))
341341
fi
@@ -629,7 +629,7 @@ _scan_run_native() {
629629
if [ -s "$_hash_hit_paths" ]; then
630630
grep -vFxf "$_hash_hit_paths"
631631
else
632-
cat
632+
command cat
633633
fi
634634
} > "$_sha256_batch_flist"
635635
command rm -f "$_hash_hit_paths"
@@ -709,7 +709,7 @@ _scan_run_native() {
709709
if [ -s "$_hash_hit_paths" ]; then
710710
grep -vFxf "$_hash_hit_paths"
711711
else
712-
cat
712+
command cat
713713
fi
714714
} > "$_hex_filelist"
715715
command rm -f "$_hash_hit_paths"
@@ -804,7 +804,7 @@ _scan_run_native() {
804804
_hex_manifest=$(mktemp "$tmpdir/.hex_manifest.$$.XXXXXX")
805805
for _wout in "${_worker_outputs[@]}"; do
806806
if [ -f "$_wout" ] && [ -s "$_wout" ]; then
807-
cat "$_wout" >> "$_hex_manifest"
807+
command cat "$_wout" >> "$_hex_manifest"
808808
fi
809809
done
810810
_flush_hit_batch "$_hex_manifest" "$_hex_stage_label"

files/internals/lmd_session.sh

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ _session_write_header() {
7373
local _hostname _hostid_val _sig_ver_val _engine_val
7474
_hostname=$(hostname)
7575
_hostid_val="${hostid:--}"
76-
_sig_ver_val="${sig_version:-$(cat "$sigdir/maldet.sigs.ver" 2>/dev/null || echo "-")}" # safe: fallback provides sentinel when sigs.ver missing
76+
_sig_ver_val="${sig_version:-$(command cat "$sigdir/maldet.sigs.ver" 2>/dev/null || echo "-")}" # safe: fallback provides sentinel when sigs.ver missing
7777
# Determine engine — scan_clamscan=1 means ClamAV was used as the primary engine.
7878
# Native engine always runs hash+hex passes; ClamAV replaces them when enabled.
7979
# Both never run simultaneously in current architecture.
@@ -130,7 +130,7 @@ _session_legacy_check() {
130130
# auto mode: check cache first
131131
if [ -f "$sessdir/.session_format" ]; then
132132
local _cached
133-
_cached=$(cat "$sessdir/.session_format")
133+
_cached=$(command cat "$sessdir/.session_format")
134134
case "$_cached" in
135135
v1) _session_legacy_active=0; return ;;
136136
legacy) _session_legacy_active=1; return ;;
@@ -464,7 +464,7 @@ view_report() {
464464
# RESOLVE RID (newest/empty)
465465
if [ "$rid" == "newest" ] || [ "$rid" == "latest" ] || [ "$rid" == "" ]; then
466466
if [ -f "$sessdir/session.last" ]; then
467-
rid=$(cat "$sessdir/session.last")
467+
rid=$(command cat "$sessdir/session.last")
468468
else
469469
eout "{report} no recent scan session found" 1
470470
exit 1
@@ -519,7 +519,7 @@ view_report() {
519519
_alert_deliver_email "$_mailto" "$email_subj" "$_json_tmp" "" "text"
520520
eout "{report} JSON report ID $rid sent to $_mailto" 1
521521
else
522-
cat "$_json_tmp"
522+
command cat "$_json_tmp"
523523
fi
524524
command rm -f "$_json_tmp"
525525
exit 0
@@ -573,7 +573,7 @@ view_report() {
573573
local _html=""
574574
_resolve_html_for_session "$_report_file"
575575
if [ -n "$_html" ]; then
576-
cat "$_html"
576+
command cat "$_html"
577577
command rm -f "$_html"
578578
else
579579
eout "{report} HTML rendering unavailable" 1
@@ -592,7 +592,7 @@ view_report() {
592592
_lmd_render_text "$_manifest" "scan" "$_tpl_dir"
593593
command rm -f "$_manifest"
594594
else
595-
cat "$_report_file"
595+
command cat "$_report_file"
596596
fi
597597
[ -n "$_vr_tmp_session" ] && command rm -f "$_vr_tmp_session"
598598
exit 0
@@ -622,7 +622,7 @@ _inotify_trim_log() {
622622
local tmplog
623623
tmplog=$(mktemp "${inotify_log}.trim.XXXXXX")
624624
tail -n +"$((_trim + 1))" "$inotify_log" > "$tmplog" 2>/dev/null
625-
cat "$tmplog" > "$inotify_log" 2>/dev/null
625+
command cat "$tmplog" > "$inotify_log" 2>/dev/null
626626
command rm -f "$tmplog"
627627
eout "{mon} inotify log file trimmed"
628628
}
@@ -686,7 +686,7 @@ _scan_finalize_session() {
686686
# Write header + hit data to TSV
687687
_session_write_header "$nsess_hits" "scan"
688688
# Append hit records (scan_session has no header during in-flight scan)
689-
cat "$scan_session" >> "$nsess_hits"
689+
command cat "$scan_session" >> "$nsess_hits"
690690

691691
_lmd_elk_post_hits "$nsess_hits"
692692

@@ -707,7 +707,7 @@ _scan_finalize_session() {
707707
# sig_version: prefer runtime $sig_version; fall back to on-disk sigs.ver sentinel.
708708
# engine derivation mirrors _session_write_header at lines 83-87.
709709
local _idx_sig_ver _idx_quar_en _idx_completed_hr _idx_engine _idx_hashtype
710-
_idx_sig_ver="${sig_version:-$(cat "$sigdir/maldet.sigs.ver" 2>/dev/null || echo "-")}" # safe: sigs.ver may be absent on fresh install
710+
_idx_sig_ver="${sig_version:-$(command cat "$sigdir/maldet.sigs.ver" 2>/dev/null || echo "-")}" # safe: sigs.ver may be absent on fresh install
711711
_idx_quar_en="${quarantine_hits:-0}"
712712
_idx_completed_hr="${scan_end_hr:--}"
713713
if [ "${scan_clamscan:-0}" = "1" ]; then

files/internals/lmd_sigs.sh

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -549,12 +549,12 @@ gensigs() {
549549
if [ -s "$sig_user_hex_file" ]; then
550550
grep -h -vE '^\s*$' "$sig_hex_file" "$sig_user_hex_file" > "$runtime_hexstrings"
551551
else
552-
cat "$sig_hex_file" > "$runtime_hexstrings"
552+
command cat "$sig_hex_file" > "$runtime_hexstrings"
553553
fi
554554
if [ -s "$sig_user_md5_file" ]; then
555555
grep -h -vE '^\s*$' "$sig_md5_file" "$sig_user_md5_file" > "$runtime_md5"
556556
else
557-
cat "$sig_md5_file" > "$runtime_md5"
557+
command cat "$sig_md5_file" > "$runtime_md5"
558558
fi
559559
# SHA-256 runtime sigs — conditional on effective hashtype
560560
runtime_sha256=""
@@ -564,7 +564,7 @@ gensigs() {
564564
if [ -s "$sig_user_sha256_file" ]; then
565565
grep -h -vE '^\s*$' "$sig_sha256_file" "$sig_user_sha256_file" > "$runtime_sha256"
566566
else
567-
cat "$sig_sha256_file" > "$runtime_sha256"
567+
command cat "$sig_sha256_file" > "$runtime_sha256"
568568
fi
569569
elif [ -s "$sig_user_sha256_file" ]; then
570570
# Upgrade path: no base sha256v2.dat yet, only custom sigs
@@ -586,7 +586,7 @@ gensigs() {
586586
echo "{HEX}$name:0:*:$hex" >> "$runtime_ndb"
587587
fi
588588
done < <(sed 's/{HEX}//' "$sig_user_hex_file" | tr ':' '%' | grep -vE "^\s*$")
589-
cat "$sig_cav_hex_file" >> "$runtime_ndb"
589+
command cat "$sig_cav_hex_file" >> "$runtime_ndb"
590590
else
591591
command cp "$sig_cav_hex_file" "$runtime_ndb"
592592
fi
@@ -595,7 +595,7 @@ gensigs() {
595595
if [ -s "$sig_user_md5_file" ]; then
596596
# Convert user MD5 sigs from LMD format (HASH:SIZE:{MD5}name) to ClamAV .hdb format (HASH:SIZE:name)
597597
sed 's/{MD5}//' "$sig_user_md5_file" | grep -vE "^\s*$" > "$runtime_hdb"
598-
cat "$sig_cav_md5_file" >> "$runtime_hdb"
598+
command cat "$sig_cav_md5_file" >> "$runtime_hdb"
599599
else
600600
command cp "$sig_cav_md5_file" "$runtime_hdb"
601601
fi
@@ -606,7 +606,7 @@ gensigs() {
606606
runtime_hsb=$(mktemp "$tmpdir/.runtime.user.hsb.$scanid.XXXXXX")
607607
if [ -s "$sig_user_sha256_file" ]; then
608608
sed 's/{SHA256}//' "$sig_user_sha256_file" | grep -vE "^\s*$" > "$runtime_hsb"
609-
[ -f "$sig_cav_sha256_file" ] && [ -s "$sig_cav_sha256_file" ] && cat "$sig_cav_sha256_file" >> "$runtime_hsb"
609+
[ -f "$sig_cav_sha256_file" ] && [ -s "$sig_cav_sha256_file" ] && command cat "$sig_cav_sha256_file" >> "$runtime_hsb"
610610
elif [ -f "$sig_cav_sha256_file" ] && [ -s "$sig_cav_sha256_file" ]; then
611611
command cp "$sig_cav_sha256_file" "$runtime_hsb"
612612
else
@@ -689,7 +689,7 @@ gensigs() {
689689
if [ -f "$sig_user_csig_file" ] && [ -s "$sig_user_csig_file" ]; then
690690
grep -h -vE '^\s*$' "$sig_csig_file" "$sig_user_csig_file" > "$_runtime_csig"
691691
else
692-
cat "$sig_csig_file" > "$_runtime_csig"
692+
command cat "$sig_csig_file" > "$_runtime_csig"
693693
fi
694694
elif [ -f "$sig_user_csig_file" ] && [ -s "$sig_user_csig_file" ]; then
695695
grep -vE '^\s*$' "$sig_user_csig_file" > "$_runtime_csig"

0 commit comments

Comments
 (0)