fix: stabilization pass — fail-closed auth, ai flag validation, lint/config/security hardening, regression tests
gates / consistency-and-conventions (push) Successful in 26s
gates / consistency-and-conventions (push) Successful in 26s
17-point code-level audit executed via Explorer->Architect->Builder->Tester->Reviewer;
Reviewer accepted (APPROVE_WITH_NOTES; 3 block-list items resolved):
- security: telegram sender-owner AND-gate + TELEGRAM_OWNER_ID, matrix
MATRIX_ROOM_ID fail-closed, gpg --passphrase-fd 3 (no argv secret),
/dev/tcp positional-arg form (checkport/smb-client/share-lib/NET_PROBE),
eval deny-by-default + --no-command-execution carried by both chat bridges,
tty-gated --trust; config/{telegram,matrix}.env reference templates
- ai: all ExecStart flags validated against installed llama.cpp
(requested->error, default->omit+warn, CONFIG_REQUESTED_FLAGS); single-file
hf download failure rc=1 + no .hf-meta; LLAMACPP_HOST coherent;
POS_SUBCMDS + metadata gaps closed
- tooling: lint-conventions Bash-native rewrite (~24-30x faster, rules and
output byte-identical, :num restored); pos system uninstall covers all 12
libs + scale-tail + flags dir + systemd user units (|| true) + plugin
markers; anchored .bash_completion/.bashrc removal replaces sed -i '/pos/d'
- config: canonical load_env_file in lib/config-ui.sh (CRLF strip, env-wins,
XDG, LOADED_ENV_KEYS); 9 tools migrated; entertainment-lib collapsed to
wrappers; docker-compose deliberately unmigrated (source semantics)
- tests: first committed regression suite — tests/run-tests.sh zero-dep
runner + make test; 12 files / 179 checks / 0 skip / ~52s; hard skip
contract; systemd-analyze verify on generated unit PASS
Verified: make gen idempotent; make check green; make lint 0 FAIL, 0 WARN;
make test green; bash -n clean; git diff --check clean. Audit deliverables +
agent reports + AGENT_TODO Done entry included.
This commit is contained in:
+129
-86
@@ -26,21 +26,6 @@ has_regex() {
|
||||
return 1
|
||||
}
|
||||
|
||||
first_line() {
|
||||
local file="$1" re="$2"
|
||||
grep -nE "$re" "$file" 2>/dev/null | while IFS=: read -r ln rest; do
|
||||
[ -z "$ln" ] && continue
|
||||
[[ "$rest" =~ ^[[:space:]]*# ]] && continue
|
||||
printf '%s' "$ln"
|
||||
break
|
||||
done
|
||||
}
|
||||
|
||||
last_line() {
|
||||
local file="$1" re="$2"
|
||||
grep -nE "$re" "$file" 2>/dev/null | tail -1 | cut -d: -f1 || true
|
||||
}
|
||||
|
||||
# First deps guard: a `command -v` line that hard-fails the tool when the binary
|
||||
# is absent — i.e. `command -v X … || err`, `if ! command -v X …`, or a
|
||||
# `command -v X … \` multi-line continuation. Runtime capability probes like
|
||||
@@ -56,27 +41,19 @@ first_guard_line() {
|
||||
printf '%s' ""
|
||||
}
|
||||
|
||||
uses_stdin() {
|
||||
local file="$1" line heredoc=""
|
||||
while IFS= read -r line; do
|
||||
if [ -n "$heredoc" ]; then
|
||||
[ "$line" = "$heredoc" ] && heredoc=""
|
||||
continue
|
||||
fi
|
||||
local delim
|
||||
delim="$(printf '%s\n' "$line" | sed -nE 's/.*<<-?[[:space:]]*([A-Za-z0-9_]+).*/\1/p' | tail -1)"
|
||||
[ -n "$delim" ] && { heredoc="$delim"; continue; }
|
||||
case "$line" in
|
||||
*'read -'*|*'read '*|*'select '*|*'confirm '*|*'confirm('*) ;;
|
||||
*) continue ;;
|
||||
esac
|
||||
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
||||
[[ "$line" == *"/dev/tty"* ]] && continue
|
||||
[[ "$line" =~ (while|until)[[:space:]].*read ]] && continue
|
||||
[[ "$line" =~ [[:space:]]\< ]] && continue
|
||||
return 0
|
||||
done < "$file"
|
||||
return 1
|
||||
# Single-line stdin-reader test. Pure bash; no subprocess. Heredoc/while-loop
|
||||
# exclusions are handled by the caller's per-file loop state.
|
||||
_reads_stdin() {
|
||||
local ln="$1"
|
||||
case "$ln" in
|
||||
*'read -'*|*'read '*|*'select '*|*'confirm '*|*'confirm('*) ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
[[ "$ln" =~ ^[[:space:]]*# ]] && return 1
|
||||
[[ "$ln" == *"/dev/tty"* ]] && return 1
|
||||
[[ "$ln" =~ (while|until)[[:space:]].*read ]] && return 1
|
||||
[[ "$ln" =~ [[:space:]]\< ]] && return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
INTERACTIVE_CMDS=""
|
||||
@@ -89,10 +66,11 @@ for f in $(shell_files); do
|
||||
case "$f" in
|
||||
lib/*.sh) continue ;; # libraries are sourced, never executed
|
||||
esac
|
||||
if ! head -1 "$f" | grep -q '^#!/usr/bin/env bash'; then
|
||||
read -r first < "$f" || first=""
|
||||
if [ "$first" != '#!/usr/bin/env bash' ]; then
|
||||
fail "$f: missing '#!/usr/bin/env bash' shebang"
|
||||
fi
|
||||
if ! has_regex "$f" '^set -euo pipefail'; then
|
||||
if ! grep -qE '^set -euo pipefail' "$f"; then
|
||||
fail "$f: missing 'set -euo pipefail'"
|
||||
fi
|
||||
done
|
||||
@@ -104,18 +82,69 @@ for f in $(executable_files); do
|
||||
fi
|
||||
done
|
||||
|
||||
# Preload DOC/POS.md once — the per-tool presence check below must not re-read
|
||||
# the file (and re-spawn grep) for every tool.
|
||||
posmd=""
|
||||
[ -f DOC/POS.md ] && posmd="$(cat DOC/POS.md)"
|
||||
|
||||
for f in bin/pos-*; do
|
||||
[ -f "$f" ] || continue
|
||||
|
||||
headline="$(sed -n '/^# POS: /{s/^# POS: //;p;q}' "$f" 2>/dev/null)"
|
||||
# ── single-pass metadata scan (shebang/pos-header/help/local/stdin) ──
|
||||
headline=""
|
||||
posline=0
|
||||
local_line=""
|
||||
help_line=""
|
||||
uses_stdin=0
|
||||
lineno=0 heredoc="" depth=0
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
lineno=$((lineno + 1))
|
||||
# # POS: header (whole-file scan, matches original `sed -n '/^# POS: /…'`)
|
||||
if [ "$posline" -eq 0 ] && [[ "$line" == "# POS: "* ]]; then
|
||||
posline=$lineno
|
||||
headline="${line#*POS: }"
|
||||
fi
|
||||
# First non-comment -h|--help line (matches original first_line lookup)
|
||||
if [ -z "$help_line" ] && ! [[ "$line" =~ ^[[:space:]]*# ]] && [[ "$line" == *-h* || "$line" == *--help* ]] && [[ "$line" =~ -h\|--help ]]; then
|
||||
help_line=$lineno
|
||||
fi
|
||||
[ -n "$heredoc" ] && { [ "$line" = "$heredoc" ] && heredoc=""; continue; }
|
||||
# Heredoc delimiter: greedy `.*` selects the LAST << / <<- on the line,
|
||||
# matching the original sed `s/.*<<-?[[:space:]]*([A-Za-z0-9_]+).*/\1/p | tail -1`.
|
||||
if [[ "$line" == *"<<"* ]] && [[ "$line" =~ .*\<\<-?[[:space:]]*([A-Za-z0-9_]+) ]]; then
|
||||
heredoc="${BASH_REMATCH[1]}"
|
||||
continue
|
||||
fi
|
||||
# Top-level `local` (WARN) — first occurrence at brace depth 0. Depth
|
||||
# tracking is only needed until the first one is found, so the two
|
||||
# full-line brace-count expansions are gated off after that.
|
||||
if [ -z "$local_line" ]; then
|
||||
if [[ "$line" == *local* ]] && [[ "$line" =~ ^[[:space:]]*local[[:space:]] ]]; then
|
||||
if [ "$depth" -eq 0 ]; then
|
||||
[ -n "$local_line" ] || local_line="$lineno"
|
||||
fi
|
||||
fi
|
||||
opens="${line//[^{]/}"
|
||||
closes="${line//[^\}]/}"
|
||||
depth=$((depth + ${#opens} - ${#closes}))
|
||||
[ "$depth" -lt 0 ] && depth=0
|
||||
fi
|
||||
# stdin-reader detection (non-heredoc lines only; cheap string gate
|
||||
# keeps the expensive regex work inside `_reads_stdin` for read-like lines)
|
||||
if [ "$uses_stdin" -eq 0 ]; then
|
||||
case "$line" in
|
||||
*'read -'*|*'read '*|*'select '*|*'confirm '*|*'confirm('*) _reads_stdin "$line" && uses_stdin=1 ;;
|
||||
esac
|
||||
fi
|
||||
done < "$f"
|
||||
|
||||
if [ -z "$headline" ]; then
|
||||
fail "$f: missing '# POS:' header"
|
||||
continue
|
||||
fi
|
||||
if ! grep -q ' — ' <<<"$headline"; then
|
||||
if [[ "$headline" != *' — '* ]]; then
|
||||
fail "$f: '# POS:' header missing em-dash ' — ' (format: '# POS: <cat> <cmd> — <desc>')"
|
||||
fi
|
||||
posline="$(grep -nE '^# POS: ' "$f" | head -1 | cut -d: -f1 || true)"
|
||||
if [ "${posline:-99}" -gt 6 ]; then
|
||||
warn_ "$f: '# POS:' header on line $posline (convention: right after shebang/strict-mode)"
|
||||
fi
|
||||
@@ -125,48 +154,23 @@ for f in bin/pos-*; do
|
||||
fi
|
||||
|
||||
guard="$(first_guard_line "$f")"
|
||||
help_line="$(first_line "$f" '\-h\|\-\-help')"
|
||||
if [ -n "$guard" ] && [ -n "$help_line" ] && [ "$help_line" -lt "$guard" ]; then
|
||||
fail "$f: -h|--help (line $help_line) dispatched before deps guards (line $guard) — help must error on missing deps"
|
||||
fi
|
||||
|
||||
local_line=""
|
||||
lineno=0
|
||||
depth=0
|
||||
heredoc=""
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
lineno=$((lineno + 1))
|
||||
if [ -n "$heredoc" ]; then
|
||||
[ "$line" = "$heredoc" ] && heredoc=""
|
||||
continue
|
||||
fi
|
||||
delim="$(printf '%s\n' "$line" | sed -nE 's/.*<<-?[[:space:]]*([A-Za-z0-9_]+).*/\1/p' | tail -1)"
|
||||
if [ -n "$delim" ]; then
|
||||
heredoc="$delim"
|
||||
continue
|
||||
fi
|
||||
if [[ "$line" =~ ^[[:space:]]*local[[:space:]] ]]; then
|
||||
if [ "$depth" -eq 0 ]; then
|
||||
[ -n "$local_line" ] || local_line="$lineno"
|
||||
fi
|
||||
fi
|
||||
opens="${line//[^{]/}"
|
||||
closes="${line//[^\}]/}"
|
||||
depth=$((depth + ${#opens} - ${#closes}))
|
||||
[ "$depth" -lt 0 ] && depth=0
|
||||
done < "$f"
|
||||
if [ -n "$local_line" ]; then
|
||||
warn_ "$f: '$local_line': 'local' at top-level brace depth (invalid in bash outside a function)"
|
||||
fi
|
||||
|
||||
if uses_stdin "$f"; then
|
||||
if [ "$uses_stdin" -eq 1 ]; then
|
||||
name="${f#bin/pos-}"
|
||||
if ! [[ " $INTERACTIVE_CMDS " == *" $name "* ]]; then
|
||||
fail "$f: reads stdin but NOT in INTERACTIVE_CMDS in bin/pos (log tee will swallow/hang prompts)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! grep -q "$(basename "$f")" DOC/POS.md 2>/dev/null; then
|
||||
base="${f#bin/}"
|
||||
if ! [[ "$posmd" == *"$base"* ]]; then
|
||||
warn_ "$f: file not referenced in DOC/POS.md"
|
||||
fi
|
||||
done
|
||||
@@ -226,35 +230,74 @@ for f in bin/wr-* bin/mp3 bin/mp4 bin/vbox bin/ssh-load-all; do
|
||||
fi
|
||||
done
|
||||
|
||||
# Secret-like literal assignment scan (WARN). Original used a grep pre-filter
|
||||
# + a per-line heredoc grep; here both are bash `[[ =~ ]]` in one read per file.
|
||||
while IFS= read -r f; do
|
||||
[ -f "$f" ] || continue
|
||||
num=0
|
||||
while IFS= read -r line; do
|
||||
[[ "$line" =~ ^[0-9]+: ]] || continue
|
||||
num="${line%%:*}"
|
||||
body="${line#*:}"
|
||||
if grep -qE '(TOKEN|PASSWORD|PASSWD|SECRET|API[_-]?KEY|ACCESS[_-]?TOKEN|AUTH[_-]?KEY)=' <<<"$body"; then
|
||||
val="${body#*=}"
|
||||
case "$val" in
|
||||
""|*'$'*) ;;
|
||||
*) warn_ "$f:$num: secret-like literal assignment (manual review for hardcoded credentials)" ;;
|
||||
esac
|
||||
fi
|
||||
done < <(grep -nE '^[[:space:]]*[A-Za-z_][A-Za-z0-9_]*(TOKEN|PASSWORD|PASSWD|SECRET|API[_-]?KEY|ACCESS[_-]?TOKEN|AUTH[_-]?KEY)=' "$f" 2>/dev/null || true)
|
||||
num=$((num + 1))
|
||||
# cheap substring gate before the expensive assignment regex
|
||||
[[ "$line" == *TOKEN* || "$line" == *PASSWORD* || "$line" == *PASSWD* || "$line" == *SECRET* || "$line" == *API* || "$line" == *ACCESS* || "$line" == *KEY* || "$line" == *AUTH* ]] || continue
|
||||
[[ "$line" =~ ^[[:space:]]*[A-Za-z_][A-Za-z0-9_]*(TOKEN|PASSWORD|PASSWD|SECRET|API[_-]?KEY|ACCESS[_-]?TOKEN|AUTH[_-]?KEY)= ]] || continue
|
||||
[[ "$line" =~ (TOKEN|PASSWORD|PASSWD|SECRET|API[_-]?KEY|ACCESS[_-]?TOKEN|AUTH[_-]?KEY)= ]] || continue
|
||||
val="${line#*=}"
|
||||
case "$val" in
|
||||
""|*'$'*) ;;
|
||||
*) warn_ "$f:$num: secret-like literal assignment (manual review for hardcoded credentials)" ;;
|
||||
esac
|
||||
done < "$f"
|
||||
done < <(printf '%s\n' bin/pos bin/pos-* lib/*.sh features/*.sh entertainment/*.sh install.sh preinstall.sh postinstall.sh)
|
||||
|
||||
# Early-occurrence scan for one of the three system paths in a line.
|
||||
# strindex sets the global _SI to the index of $2 in $1 (or 2147483647 if absent).
|
||||
_SI=0
|
||||
strindex() { local pre="${1%%"$2"*}"; if [ "$pre" = "$1" ]; then _SI=2147483647; else _SI=${#pre}; fi; }
|
||||
|
||||
# Faithful re-implementation of the original outer filter
|
||||
# grep -E '(\btee\b|>>?)[^#]*?(/etc/|\$HOME|/usr/local)'
|
||||
# (operator, then any non-'#' chars, then a system path). Bash `=~` does not
|
||||
# honour the lazy `[^#]*?` the same way, so we walk path occurrences manually,
|
||||
# checking that the segment before each path (after the last '#') holds an
|
||||
# operator (`>`/`>>` or a word-bounded `tee`).
|
||||
_syspath_outer() {
|
||||
local ln="$1" best=2147483647 bestcand="" idx c pre seg h
|
||||
for c in '/etc/' '$HOME' '/usr/local'; do
|
||||
strindex "$ln" "$c"
|
||||
[ "$_SI" -lt "$best" ] && { best="$_SI"; bestcand="$c"; }
|
||||
done
|
||||
[ "$best" -ge 2147483647 ] && return 1
|
||||
pre="${ln:0:best}"
|
||||
h="${pre%#*}"
|
||||
if [ "$h" = "$pre" ]; then
|
||||
seg="$pre" # no '#' before the path
|
||||
else
|
||||
seg="${pre:${#h}+1}" # after the last '#' before the path
|
||||
fi
|
||||
if [[ "$seg" == *">"* ]] || [[ "$seg" =~ \btee\b ]]; then
|
||||
return 0
|
||||
fi
|
||||
_syspath_outer "${ln:best+${#bestcand}}"
|
||||
}
|
||||
|
||||
# System-path write scan (WARN). Route lines through the same outer filter then
|
||||
# the same per-line heuristic the original applied (check + exclusions).
|
||||
while IFS= read -r f; do
|
||||
[ -f "$f" ] || continue
|
||||
num=0
|
||||
while IFS= read -r line; do
|
||||
[[ "$line" =~ ^[0-9]+: ]] || continue
|
||||
num="${line%%:*}"
|
||||
body="${line#*:}"
|
||||
if grep -qE '(>|>>|tee )' <<<"$body" && grep -qE '(/etc/|\$HOME|/usr/local)' <<<"$body"; then
|
||||
case "$body" in
|
||||
num=$((num + 1))
|
||||
# cheap string gate: outer filter needs both an operator and a path
|
||||
[[ "$line" == *">"* || "$line" == *tee* ]] || continue
|
||||
[[ "$line" == */etc/* || "$line" == *'$HOME'* || "$line" == */usr/local* ]] || continue
|
||||
_syspath_outer "$line" || continue
|
||||
if [[ "$line" =~ (>|>>|tee[[:space:]]) ]] && [[ "$line" =~ (/etc/|\$HOME|/usr/local) ]]; then
|
||||
case "$line" in
|
||||
*'command -v'*|*'|| echo'*) ;;
|
||||
*) warn_ "$f:$num: writes to a system path (verify a VAR=\"\${VAR:-path}\" test seam exists)" ;;
|
||||
esac
|
||||
fi
|
||||
done < <(grep -nE '(\btee\b|>>?)[^#]*?(/etc/|\$HOME|/usr/local)' "$f" 2>/dev/null || true)
|
||||
done < "$f"
|
||||
done < <(printf '%s\n' bin/pos-* lib/*.sh features/*.sh entertainment/*.sh)
|
||||
|
||||
printf '\n%d FAIL, %d WARN (convention lint)\n' "$fails" "$warns"
|
||||
|
||||
Reference in New Issue
Block a user