Skip to content

GH#2899: Fix quality-debt review feedback on memory-pressure-monitor.sh#2930

Merged
marcusquinn merged 1 commit intomainfrom
bugfix/memory-pressure-review-fixes
Mar 5, 2026
Merged

GH#2899: Fix quality-debt review feedback on memory-pressure-monitor.sh#2930
marcusquinn merged 1 commit intomainfrom
bugfix/memory-pressure-review-fixes

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Mar 5, 2026

Summary

Addresses all 5 unactioned review findings from PR #2884 (Gemini code review) on .agents/scripts/memory-pressure-monitor.sh.

# Severity Finding Fix
1 HIGH AppleScript injection via osascript -e string interpolation — crafted process names could break out of the string literal and execute arbitrary commands Replaced with osascript - "$title" "$message" stdin piping using on run argv — values are never interpolated into AppleScript source
2 MEDIUM MEMORY_COOLDOWN_SECS not validated before use in arithmetic context — exploitable via a[$(cmd)] injection Added _validate_int() call for both COOLDOWN_SECS and DAEMON_INTERVAL, then readonly
3 MEDIUM Redundant 2>/dev/null on cat after [[ -f ]] existence check masks permission errors Removed 2>/dev/null — the `
4 MEDIUM Process collection loop spawns echo|awk|cut subshells per line (inefficient) Replaced with read -r pid rss_kb cmd builtin + ${cmd%% *} parameter expansion
5 MEDIUM Session counting loop spawns echo|awk subshell per line (inefficient) Replaced with read -r _ tty _ builtin

Verification

  • ShellCheck: zero violations
  • Tests: 28/28 passed (all existing tests)

Closes #2899

Summary by CodeRabbit

  • Bug Fixes

    • Improved error handling for cooldown timestamp reading with fallback behavior.
    • Hardened notification implementation to reduce security risks.
  • Performance

    • Optimized process parsing to reduce overhead and improve efficiency.
    • Simplified interactive session parsing for faster execution.
  • Chores

    • Added validation for configuration parameters with numeric bounds checking.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c5ffccdf-074c-4a00-8b01-5704c90e7dce

📥 Commits

Reviewing files that changed from the base of the PR and between 500ec77 and 37d9aad.

📒 Files selected for processing (1)
  • .agents/scripts/memory-pressure-monitor.sh

Walkthrough

This pull request hardens the memory pressure monitor script by addressing security vulnerabilities and performance inefficiencies. Changes include validating integer configuration variables before use, replacing unsafe osascript interpolation with stdin-based parameter passing, removing blanket error suppression, and optimizing process/session parsing to use shell builtins instead of subshells.

Changes

Cohort / File(s) Summary
Security & Validation Hardening
.agents/scripts/memory-pressure-monitor.sh
Validates COOLDOWN_SECS and DAEMON_INTERVAL via _validate_int function before readonly assignment. Refactors osascript invocation to pass title/message as positional arguments via stdin instead of interpolated strings, preventing command injection through process names. Removes redundant 2>/dev/null error suppression from cooldown file read operation.
Performance Optimization
.agents/scripts/memory-pressure-monitor.sh
Refactors _collect_monitored_processes to use read builtin for line parsing instead of per-line awk/cut subshells. Simplifies command name extraction via parameter expansion and basename. Updates _count_interactive_sessions to use read builtin for TTY field parsing, eliminating per-line echo/awk subshell overhead.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

bug

Poem

🛡️ With read in place of spawned shells so grand,
And validation guarding each config demand,
The osascript now flows through stdin's safe hand,
No more injection tricks could slip through the sand!
Performance and security, perfectly planned. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ❓ Inconclusive While the PR includes unrelated fixes in auto-update-helper.sh and tool-version-check.sh for macOS timeout/timezone issues, the primary focus and title correctly target memory-pressure-monitor.sh changes addressing issue #2899; ancillary script improvements appear to support the main objective without contradicting stated scope. Clarify whether fixes to auto-update-helper.sh, tool-version-check.sh, and aidevops.sh are intentional scope expansions or should be split into separate PRs aligned with their respective issues.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly references the primary objective: fixing quality-debt review feedback on memory-pressure-monitor.sh as tracked in issue #2899.
Linked Issues check ✅ Passed All five coding requirements from issue #2899 are met: AppleScript injection prevention via stdin, validation of COOLDOWN_SECS/DAEMON_INTERVAL, removal of redundant stderr suppression, and replacement of subshell loops with read-based parsing in both process collection and session counting.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/memory-pressure-review-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses several quality-debt issues and review feedback items identified in the memory-pressure-monitor.sh script. The changes primarily focus on enhancing security by preventing AppleScript injection and validating integer inputs, improving robustness by clarifying error handling, and boosting efficiency by optimizing shell command parsing to reduce subshell spawns. Additionally, it introduces a portable timeout function and refines timestamp handling across various scripts.

Highlights

  • AppleScript Injection Prevention: Replaced osascript -e string interpolation with osascript - "$title" "$message" using on run argv to prevent arbitrary command execution via crafted process names.
  • Integer Validation: Added _validate_int() calls for COOLDOWN_SECS and DAEMON_INTERVAL and made them readonly after validation, preventing a[$(cmd)] injection.
  • Redundant Error Suppression Removal: Removed 2>/dev/null from cat command after [[ -f ]] check, allowing permission errors to surface while maintaining graceful fallback.
  • Process Collection Optimization: Replaced inefficient echo|awk|cut subshells with read -r pid rss_kb cmd builtin and ${cmd%% *} parameter expansion for process parsing.
  • Session Counting Optimization: Replaced inefficient echo|awk subshell with read -r _ tty _ builtin for interactive session counting.
Changelog
  • .agents/scripts/auto-update-helper.sh
    • Ensured UTC timezone is explicitly set for date commands on macOS to correctly parse timestamps.
  • .agents/scripts/memory-pressure-monitor.sh
    • Modified COOLDOWN_SECS and DAEMON_INTERVAL to be validated as integers before being set as readonly.
    • Refactored osascript calls to use on run argv with stdin piping, mitigating AppleScript injection vulnerabilities.
    • Removed redundant 2>/dev/null from cat command when checking cooldown files, improving error visibility.
    • Optimized process collection by replacing external echo|awk|cut commands with read -r builtin for parsing.
    • Improved session counting efficiency by using read -r builtin instead of echo|awk.
    • Updated command name extraction to use parameter expansion for better performance.
  • .agents/scripts/tool-version-check.sh
    • Implemented a robust timeout mechanism using temporary files for version checks to prevent hangs on macOS.
    • Applied the new timeout mechanism with temporary files to update commands to ensure reliability.
  • aidevops.sh
    • Introduced a new portable _timeout_cmd function to provide consistent timeout functionality across different operating systems (Linux timeout, macOS gtimeout or perl fallback).
    • Integrated the _timeout_cmd function into cmd_update for more reliable package version retrieval.
Activity
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.agents/scripts/memory-pressure-monitor.sh (1)

322-326: Replace basename subprocess with pure parameter expansion in the hot process loop.

Line 325 spawns basename inside a nested loop processing monitored processes. This should use bash parameter expansion for consistency with the stated intent on line 322 and to eliminate subprocess overhead in a hot path.

Proposed fix
-			local cmd_path="${cmd%% *}"
-			local cmd_name
-			cmd_name=$(basename "$cmd_path" 2>/dev/null || echo "unknown")
+			local cmd_path="${cmd%% *}"
+			local cmd_name="${cmd_path##*/}"
+			[[ -n "$cmd_name" ]] || cmd_name="unknown"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/memory-pressure-monitor.sh around lines 322 - 326, Replace
the subprocess call to basename with pure parameter expansion: instead of
cmd_name=$(basename "$cmd_path" 2>/dev/null || echo "unknown"), compute cmd_name
from cmd_path using ${cmd_path##*/} and fallback to "unknown" when empty (e.g.,
cmd_name="${cmd_path##*/}"; [ -z "$cmd_name" ] && cmd_name="unknown"). This
keeps the existing extraction logic (cmd_path="${cmd%% *}") and removes the
basename subprocess inside the hot loop.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@aidevops.sh`:
- Line 867: The piped call to `_timeout_cmd 30 brew info --json=v2 "$brew_pkg" |
jq -r ...` can hang when the perl fallback is used; change the pattern to write
`_timeout_cmd` stdout to a temporary file, run `jq` against that temp file to
extract `.formulae[0].versions.stable`, assign the result to `latest`, and
ensure the temp file is removed (use mktemp and rm or a short-lived
subshell/trap) so the command no longer relies on a direct pipe between
`_timeout_cmd` and `jq`.

---

Nitpick comments:
In @.agents/scripts/memory-pressure-monitor.sh:
- Around line 322-326: Replace the subprocess call to basename with pure
parameter expansion: instead of cmd_name=$(basename "$cmd_path" 2>/dev/null ||
echo "unknown"), compute cmd_name from cmd_path using ${cmd_path##*/} and
fallback to "unknown" when empty (e.g., cmd_name="${cmd_path##*/}"; [ -z
"$cmd_name" ] && cmd_name="unknown"). This keeps the existing extraction logic
(cmd_path="${cmd%% *}") and removes the basename subprocess inside the hot loop.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 59aa9722-2a63-48da-8475-f8999773366d

📥 Commits

Reviewing files that changed from the base of the PR and between fefa759 and 500ec77.

📒 Files selected for processing (4)
  • .agents/scripts/auto-update-helper.sh
  • .agents/scripts/memory-pressure-monitor.sh
  • .agents/scripts/tool-version-check.sh
  • aidevops.sh

…2884

- HIGH: Fix AppleScript injection in notify() — pass script via stdin
  with 'on run argv' instead of -e string interpolation, preventing
  breakout via crafted process names
- MEDIUM: Validate MEMORY_COOLDOWN_SECS and DAEMON_INTERVAL with
  _validate_int() to prevent arithmetic expansion injection
- MEDIUM: Remove redundant 2>/dev/null on cat after file existence check
  to surface permission errors for debugging
- MEDIUM: Optimize _collect_monitored_processes() loop — use read builtin
  and parameter expansion instead of echo|awk|cut subshells per line
- MEDIUM: Optimize _count_interactive_sessions() loop — use read builtin
  instead of echo|awk subshell per line

Closes #2899
@marcusquinn marcusquinn force-pushed the bugfix/memory-pressure-review-fixes branch from 500ec77 to 37d9aad Compare March 5, 2026 16:32
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses several quality and security issues in memory-pressure-monitor.sh, including a critical command injection vulnerability. The fixes are well-implemented and significantly improve the script's robustness and performance. The introduction of a portable _timeout_cmd function is also a valuable addition. My review focuses on ensuring this new utility is used safely across all files and that resource management is robust. I've identified one critical issue where _timeout_cmd is piped in a way that can cause hangs on macOS, and a couple of medium-severity opportunities to improve temporary file cleanup using project-established patterns and to avoid suppressing diagnostic output.

I am having trouble creating individual review comments. Click here to see my feedback.

aidevops.sh (867)

critical

The new _timeout_cmd is a great portable utility. However, its output is being piped directly to jq. As noted in the changes to tool-version-check.sh, the perl fallback for timeout on macOS can cause the downstream command in a pipe (in this case, jq) to hang if a timeout occurs. To ensure robustness on all platforms, please use a temporary file here, just as you did in tool-version-check.sh. Additionally, avoid suppressing stderr with 2>/dev/null as this can mask important diagnostic information, as per project guidelines.

latest=$( (\n    local _info_log\n    _info_log=$(mktemp "${TMPDIR:-/tmp}/brew-info.XXXXXX")\n    # Ensure cleanup on subshell exit\n    trap 'rm -f "$_info_log"' EXIT\n    if _timeout_cmd 30 brew info --json=v2 "$brew_pkg" >"$_info_log"; then\n        jq -r '.formulae[0].versions.stable // empty' "$_info_log"\n    fi\n) || true)
References
  1. Suppressing stderr with 2>/dev/null can mask important diagnostic information, such as permissions problems or other issues, and should be avoided.

.agents/scripts/tool-version-check.sh (121-129)

medium

To make temporary file cleanup robust and align with the project's established pattern, please use push_cleanup for $_ver_log. This ensures the file is removed even if the function exits unexpectedly. Additionally, avoid suppressing stderr with 2>/dev/null as this can mask important diagnostic information, as per project guidelines.

local _ver_log
_ver_log=$(mktemp "${TMPDIR:-/tmp}/tool-ver.XXXXXX")
push_cleanup "rm -f \"$_ver_log\""
# shellcheck disable=SC2086
timeout_sec 5 "$cmd" $ver_flag >"$_ver_log" || true
version=$(head -1 "$_ver_log" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "")
if [[ -z "$version" ]]; then
	version=$(head -1 "$_ver_log" | grep -oE '[0-9]+\.[0-9]+' | head -1 || echo "unknown")
fi
rm -f "$_ver_log"
References
  1. The project has an established pattern for robust resource cleanup using _save_cleanup_scope, trap '_run_cleanups' RETURN, and push_cleanup to ensure resources are cleaned up on any exit path, including unexpected ones.
  2. Suppressing stderr with 2>/dev/null can mask important diagnostic information, such as permissions problems or other issues, and should be avoided.

.agents/scripts/tool-version-check.sh (386-395)

medium

To ensure robust temporary file cleanup for $_update_log and align with the project's established pattern, please use push_cleanup. This ensures the file is removed even if the script exits unexpectedly.

local _update_log
_update_log=$(mktemp "${TMPDIR:-/tmp}/tool-update.XXXXXX")
push_cleanup "rm -f \"$_update_log\""
if timeout_sec 120 bash -c "$update_cmd" >"$_update_log" 2>&1; then
	tail -2 "$_update_log"
	echo -e "  ${GREEN}✓ Updated${NC}"
else
	tail -2 "$_update_log"
	echo -e "  ${RED}✗ Failed${NC}"
fi
rm -f "$_update_log"
References
  1. The project has an established pattern for robust resource cleanup using _save_cleanup_scope, trap '_run_cleanups' RETURN, and push_cleanup to ensure resources are cleaned up on any exit path, including unexpected ones.

@marcusquinn marcusquinn merged commit 92ee17c into main Mar 5, 2026
4 of 6 checks passed
@marcusquinn marcusquinn deleted the bugfix/memory-pressure-review-fixes branch March 5, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

quality-debt: .agents/scripts/memory-pressure-monitor.sh — PR #2884 review feedback (high)

1 participant