From dad309dce40f1b10cb971bd85979a2ba1eb85cbf Mon Sep 17 00:00:00 2001 From: marcusquinn <6428977+marcusquinn@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:47:56 +0000 Subject: [PATCH 1/2] fix: t2950 remove error suppression from consent persistence and quote crontab variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove 2>/dev/null from cmd_set calls that persist supervisor pulse consent — errors should be visible so users understand why consent wasn't saved. Remove redundant 2>/dev/null from grep where file existence is already checked. Single-quote variables in crontab entry to prevent command injection via directory names with metacharacters. --- setup.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.sh b/setup.sh index b66c99517e..a7d6d657d1 100755 --- a/setup.sh +++ b/setup.sh @@ -770,7 +770,7 @@ main() { # Also check legacy .conf user override if [[ -z "$_pulse_user_config" && -f "${FEATURE_TOGGLES_USER:-$HOME/.config/aidevops/feature-toggles.conf}" ]]; then local _legacy_val - _legacy_val=$(grep -E '^supervisor_pulse=' "${FEATURE_TOGGLES_USER:-$HOME/.config/aidevops/feature-toggles.conf}" 2>/dev/null | tail -1 | cut -d= -f2) + _legacy_val=$(grep -E '^supervisor_pulse=' "${FEATURE_TOGGLES_USER:-$HOME/.config/aidevops/feature-toggles.conf}" | tail -1 | cut -d= -f2) if [[ -n "$_legacy_val" ]]; then _pulse_user_config="$_legacy_val" fi @@ -812,13 +812,13 @@ main() { _do_install=true # Record explicit consent if type cmd_set &>/dev/null; then - cmd_set "orchestration.supervisor_pulse" "true" 2>/dev/null || true + cmd_set "orchestration.supervisor_pulse" "true" || true fi else _do_install=false # Record explicit decline so we never re-prompt on updates if type cmd_set &>/dev/null; then - cmd_set "orchestration.supervisor_pulse" "false" 2>/dev/null || true + cmd_set "orchestration.supervisor_pulse" "false" || true fi print_info "Skipped. Enable later: aidevops config set orchestration.supervisor_pulse true && ./setup.sh" fi @@ -921,7 +921,7 @@ PLIST # Remove old-style cron entries (direct opencode invocation) ( crontab -l 2>/dev/null | grep -v 'aidevops: supervisor-pulse' - echo "*/2 * * * * OPENCODE_BIN=${opencode_bin} PULSE_DIR=${_aidevops_dir} /bin/bash ${wrapper_script} >> $HOME/.aidevops/logs/pulse-wrapper.log 2>&1 # aidevops: supervisor-pulse" + echo "*/2 * * * * OPENCODE_BIN='${opencode_bin}' PULSE_DIR='${_aidevops_dir}' /bin/bash '${wrapper_script}' >> '$HOME/.aidevops/logs/pulse-wrapper.log' 2>&1 # aidevops: supervisor-pulse" ) | crontab - 2>/dev/null || true if crontab -l 2>/dev/null | grep -qF "aidevops: supervisor-pulse"; then print_info "Supervisor pulse enabled (cron, every 2 min). Disable: crontab -e and remove the supervisor-pulse line" From e633c8f2a65b49baa95016f86a22c4cf338e1ae3 Mon Sep 17 00:00:00 2001 From: marcusquinn <6428977+marcusquinn@users.noreply.github.com> Date: Fri, 6 Mar 2026 16:10:36 +0000 Subject: [PATCH 2/2] fix: address CodeRabbit CHANGES_REQUESTED review feedback on PR #2994 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Replace grep|tail|cut pipeline with awk for legacy config read — grep exits 1 on no match, which aborts the script under set -euo pipefail. awk always exits 0 and handles the missing-key case safely. 2. Add shell_single_quote() utility and use it for crontab path interpolation — prevents syntax errors and command injection when paths contain apostrophes (e.g. /home/O'Connor/...). Both findings verified with functional tests. ShellCheck clean. --- setup.sh | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/setup.sh b/setup.sh index a7d6d657d1..68a9f15a1c 100755 --- a/setup.sh +++ b/setup.sh @@ -94,6 +94,16 @@ _launchd_has_agent() { return $? } +# Escape a string for safe embedding inside single quotes. +# Replaces each ' with '"'"' (end quote, double-quoted apostrophe, resume quote). +# Usage: local safe_path; safe_path="$(shell_single_quote "$path")" +# echo "CMD='${safe_path}'" +shell_single_quote() { + local input="$1" + printf '%s' "$input" | sed "s/'/'\"\\'\"'/g" + return 0 +} + # Spinner for long-running operations # Usage: run_with_spinner "Installing package..." command arg1 arg2 run_with_spinner() { @@ -770,7 +780,9 @@ main() { # Also check legacy .conf user override if [[ -z "$_pulse_user_config" && -f "${FEATURE_TOGGLES_USER:-$HOME/.config/aidevops/feature-toggles.conf}" ]]; then local _legacy_val - _legacy_val=$(grep -E '^supervisor_pulse=' "${FEATURE_TOGGLES_USER:-$HOME/.config/aidevops/feature-toggles.conf}" | tail -1 | cut -d= -f2) + # Use awk instead of grep|tail|cut — grep exits 1 on no match, which + # aborts the script under set -euo pipefail. awk always exits 0. + _legacy_val=$(awk -F= '/^supervisor_pulse=/{val=$2} END{print val}' "${FEATURE_TOGGLES_USER:-$HOME/.config/aidevops/feature-toggles.conf}") if [[ -n "$_legacy_val" ]]; then _pulse_user_config="$_legacy_val" fi @@ -919,9 +931,16 @@ PLIST else # Linux: use cron entry with wrapper # Remove old-style cron entries (direct opencode invocation) + # Escape paths for safe embedding in single-quoted crontab entry + # (handles apostrophes in paths, e.g. /home/O'Connor/...) + local _cron_opencode_q _cron_pulsedir_q _cron_wrapper_q _cron_log_q + _cron_opencode_q="$(shell_single_quote "$opencode_bin")" + _cron_pulsedir_q="$(shell_single_quote "$_aidevops_dir")" + _cron_wrapper_q="$(shell_single_quote "$wrapper_script")" + _cron_log_q="$(shell_single_quote "$HOME/.aidevops/logs/pulse-wrapper.log")" ( crontab -l 2>/dev/null | grep -v 'aidevops: supervisor-pulse' - echo "*/2 * * * * OPENCODE_BIN='${opencode_bin}' PULSE_DIR='${_aidevops_dir}' /bin/bash '${wrapper_script}' >> '$HOME/.aidevops/logs/pulse-wrapper.log' 2>&1 # aidevops: supervisor-pulse" + echo "*/2 * * * * OPENCODE_BIN='${_cron_opencode_q}' PULSE_DIR='${_cron_pulsedir_q}' /bin/bash '${_cron_wrapper_q}' >> '${_cron_log_q}' 2>&1 # aidevops: supervisor-pulse" ) | crontab - 2>/dev/null || true if crontab -l 2>/dev/null | grep -qF "aidevops: supervisor-pulse"; then print_info "Supervisor pulse enabled (cron, every 2 min). Disable: crontab -e and remove the supervisor-pulse line"