Skip to content

t1398.1: Add process resource guard to pulse-wrapper.sh#2881

Merged
alex-solovyev merged 1 commit intomainfrom
bugfix/t1398.1-process-resource-guard
Mar 5, 2026
Merged

t1398.1: Add process resource guard to pulse-wrapper.sh#2881
alex-solovyev merged 1 commit intomainfrom
bugfix/t1398.1-process-resource-guard

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Mar 5, 2026

Summary

  • Adds cleanup_runaway_processes() to pulse-wrapper.sh that kills child processes exceeding configurable RSS limit (2GB default) or runtime limit (10min for shellcheck)
  • Prevents single processes from consuming all RAM — root cause of the March 3 kernel panic where shellcheck with --external-sources reached 5.7GB RSS
  • Two-pass design: Pass 1 checks RSS on all framework processes (opencode, shellcheck, node); Pass 2 checks runtime specifically on shellcheck to catch exponential expansion before RSS ceiling

Design

Configuration (env var overrides with validated defaults):

  • RESOURCE_GUARD_RSS_LIMIT_KB — default 2097152 (2GB). Any framework process exceeding this RSS is killed.
  • RESOURCE_GUARD_RUNTIME_LIMIT — default 600 (10min). ShellCheck processes exceeding this runtime are killed.

Integration: Runs in main() after cleanup_orphans and before cleanup_worktrees, so it catches runaway processes from previous cycles before starting new work.

Safety:

  • Only targets framework processes (shellcheck, .opencode, node.*opencode) — never touches unrelated user processes
  • Skips self ($$)
  • Validates all numeric fields before arithmetic
  • Uses existing _kill_tree_force_kill_tree escalation pattern (SIGTERM first, SIGKILL if still alive after 1s)
  • Both config vars validated via _validate_int with minimum of 1 (prevents divide-by-zero and command injection)

Verification

  • ShellCheck: zero violations
  • bash -n: syntax OK
  • All existing functions unchanged — additive only

Closes #2874

Summary by CodeRabbit

  • Documentation
    • Updated script documentation to reflect the operational sequence, including process management for runaway processes exceeding resource and runtime limits.

@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 a critical issue of runaway processes consuming excessive system resources, which previously led to kernel panics. By introducing a robust process resource guard, the system can now automatically identify and terminate processes that exceed configurable memory or runtime limits. This enhancement significantly improves the stability and reliability of the pulse-wrapper.sh script by preventing resource exhaustion, particularly from memory-intensive operations like shellcheck with external sources.

Highlights

  • Process Resource Guard: Introduced a new cleanup_runaway_processes() function to proactively terminate child processes that exceed predefined resource limits, preventing system instability.
  • Configurable Limits: Added two new configurable environment variables: RESOURCE_GUARD_RSS_LIMIT_KB (default 2GB) for memory usage and RESOURCE_GUARD_RUNTIME_LIMIT (default 10 minutes) specifically for shellcheck processes.
  • Two-Pass Detection: Implemented a two-pass design: the first pass checks all framework processes for RSS limits, and the second pass specifically checks shellcheck processes for runtime limits to catch exponential expansion early.
  • Targeted Scope and Safety: The resource guard is designed to only target framework processes (shellcheck, .opencode, node.*opencode), validate numeric inputs, and use existing safe kill mechanisms to avoid affecting unrelated user processes.
Changelog
  • .agents/scripts/pulse-wrapper.sh
    • Updated the script's introductory comments to reflect the addition of the process resource guard.
    • Added RESOURCE_GUARD_RSS_LIMIT_KB and RESOURCE_GUARD_RUNTIME_LIMIT configuration variables with default values.
    • Integrated validation for the new resource guard configuration variables using _validate_int.
    • Inserted a call to the new cleanup_runaway_processes function within the main execution flow.
    • Implemented the cleanup_runaway_processes function, including its two-pass logic for RSS and runtime limit enforcement.
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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7d7fd65c-f868-4653-8196-2a73704bf686

📥 Commits

Reviewing files that changed from the base of the PR and between feecaaa and 545701e.

📒 Files selected for processing (1)
  • .agents/scripts/pulse-wrapper.sh

Walkthrough

This PR updates the header documentation in pulse-wrapper.sh to reflect the planned process resource guard functionality (t1398.1), repositioning the documented order of responsibilities to include the new capability that kills child processes exceeding RSS or runtime limits.

Changes

Cohort / File(s) Summary
Documentation Update
.agents/scripts/pulse-wrapper.sh
Updated header comments to document "Kills runaway processes exceeding RSS or runtime limits (t1398.1)" as item 3, shifting subsequent responsibility items accordingly. No code logic modifications.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Possibly related PRs

  • PR #2853: Updates pulse-wrapper.sh header to document the runaway process guard behavior that would be implemented in t1398.1
  • PR #2855: Related header documentation updates reflecting the process guard and ShellCheck resource limit functionality

Suggested labels

bug


📋 Headers align with hearts, scripts stand tall,
Process guards written, before code's call.
Document today, what runs tomorrow—
Runaway processes? Frame won't borrow. ⚙️✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR objectives describe a comprehensive cleanup_runaway_processes() implementation with RSS/runtime limits, but the raw summary shows only header comment changes with no functional code modifications. The actual implementation of cleanup_runaway_processes() function must be added to comply with issue #2874's core requirement of enforcing configurable resource limits on child processes.
Out of Scope Changes check ❓ Inconclusive Changes are limited to header comments in pulse-wrapper.sh describing new resource guard functionality, which aligns with PR objectives but lacks the functional implementation required by linked issue #2874. Clarify whether header-only changes are intentional or if functional code implementation of cleanup_runaway_processes() is still in progress and will be committed before merge.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the primary objective: adding a process resource guard to pulse-wrapper.sh to kill runaway processes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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/t1398.1-process-resource-guard

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.

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 introduces a resource guard to pulse-wrapper.sh to prevent runaway processes by monitoring RSS and runtime, which is a great addition for system stability. However, a critical security vulnerability has been identified: a logic error in how the current process is excluded from monitoring, which can lead to a security bypass, and a log injection vulnerability where unsanitized process command lines are written to the log file. Additionally, the review suggests improving the performance and robustness of the process-parsing loops by using more idiomatic Bash constructs and adhering to project guidelines on error handling.

killed=$((killed + 1))
total_freed_mb=$((total_freed_mb + mb))
fi
done < <(ps -axo pid,rss,command 2>/dev/null | grep -E 'shellcheck|\.opencode|node.*opencode' | grep -v grep | grep -v "$$" || true)

Choose a reason for hiding this comment

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

security-high high

A critical security bypass vulnerability exists due to the use of grep -v "$$" to exclude the current process. This method performs a substring match, which can unintentionally exclude other processes whose PID, RSS, or command line contains the script's PID as a substring. This allows runaway processes to escape termination, potentially leading to a system-wide denial-of-service. The suggested fix removes this problematic grep filter.
Additionally, the current method of parsing ps output by reading line-by-line is inefficient. A more performant approach would be to use read to parse fields directly within the while loop. While the suggested code retains 2>/dev/null for ps output, it's generally recommended to avoid suppressing ps errors to ensure potential system or command errors are visible for debugging.

Suggested change
done < <(ps -axo pid,rss,command 2>/dev/null | grep -E 'shellcheck|\.opencode|node.*opencode' | grep -v grep | grep -v "$$" || true)
done < <(ps -axo pid,rss,command 2>/dev/null | grep -E 'shellcheck|\.opencode|node.*opencode' | grep -v grep || true)
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

killed=$((killed + 1))
total_freed_mb=$((total_freed_mb + mb))
fi
done < <(ps -axo pid,etime,command 2>/dev/null | grep 'shellcheck' | grep -v grep | grep -v "$$" || true)

Choose a reason for hiding this comment

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

security-high high

Similar to the previous instance, a critical security bypass vulnerability exists here due to the use of grep -v "$$" to exclude the current process. This substring matching can unintentionally exclude other processes, allowing runaway processes to escape termination and potentially leading to a system-wide denial-of-service. The suggested fix removes this problematic grep filter.
Additionally, this loop can be made more efficient by using read to parse the ps output directly instead of using echo, awk, and cut in subshells for each line. While the suggested code retains 2>/dev/null for ps output, it's generally recommended to avoid suppressing ps errors to ensure potential system or command errors are visible for debugging.

Suggested change
done < <(ps -axo pid,etime,command 2>/dev/null | grep 'shellcheck' | grep -v grep | grep -v "$$" || true)
done < <(ps -axo pid,etime,command 2>/dev/null | grep 'shellcheck' | grep -v grep || true)
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

if [[ "$rss" -gt "$RESOURCE_GUARD_RSS_LIMIT_KB" ]]; then
local mb=$((rss / 1024))
local limit_mb=$((RESOURCE_GUARD_RSS_LIMIT_KB / 1024))
echo "[pulse-wrapper] Resource guard: killing PID $pid (RSS ${mb}MB > ${limit_mb}MB limit): ${cmd:0:120}" >>"$LOGFILE"

Choose a reason for hiding this comment

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

security-medium medium

The script logs the command line of processes it terminates to $LOGFILE. The command line (cmd) is extracted directly from the ps output and appended to the log without sanitization. An attacker who can execute processes on the system can craft a process with a malicious command line (e.g., containing newlines or fake log prefixes) to inject arbitrary entries into the log file. This can be used to mislead administrators, spoof system messages, or obfuscate malicious activity.

rss_kb=$(ps -p "$pid" -o rss= 2>/dev/null | tr -d ' ') || rss_kb=0
[[ "$rss_kb" =~ ^[0-9]+$ ]] || rss_kb=0
local mb=$((rss_kb / 1024))
echo "[pulse-wrapper] Resource guard: killing shellcheck PID $pid (runtime ${age_seconds}s > ${RESOURCE_GUARD_RUNTIME_LIMIT}s limit, RSS ${mb}MB): ${cmd:0:120}" >>"$LOGFILE"

Choose a reason for hiding this comment

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

security-medium medium

The script logs the command line of processes it terminates to $LOGFILE. The command line (cmd) is extracted directly from the ps output and appended to the log without sanitization. An attacker who can execute processes on the system can craft a process with a malicious command line (e.g., containing newlines or fake log prefixes) to inject arbitrary entries into the log file. This can be used to mislead administrators, spoof system messages, or obfuscate malicious activity.

@alex-solovyev
Copy link
Collaborator

This PR has merge conflicts after recent merges to main. Dispatching a worker to rebase and resolve conflicts.

@alex-solovyev
Copy link
Collaborator

PR is not mergeable after #2879 and #2885 landed on main. Needs rebase to resolve conflicts. Re-dispatching worker.

@alex-solovyev alex-solovyev force-pushed the bugfix/t1398.1-process-resource-guard branch from 6e4de7b to 844cffb Compare March 5, 2026 03:56
@github-actions
Copy link

github-actions bot commented Mar 5, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 107 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Thu Mar 5 03:57:12 UTC 2026: Code review monitoring started
Thu Mar 5 03:57:12 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 107

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 107
  • VULNERABILITIES: 0

Generated on: Thu Mar 5 03:57:15 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

Add cleanup_runaway_processes() that kills child processes exceeding
configurable RSS limit (2GB default) or runtime limit (10min for
shellcheck). Prevents single processes from consuming all RAM — root
cause of the March 3 kernel panic where shellcheck with
--external-sources reached 5.7GB RSS.

Two-pass design:
- Pass 1: RSS limit on all framework processes (opencode, shellcheck, node)
- Pass 2: Runtime limit specifically on shellcheck (catches exponential
  expansion before RSS ceiling)

Extends existing _kill_tree/_force_kill_tree pattern. Configurable via
RESOURCE_GUARD_RSS_LIMIT_KB and RESOURCE_GUARD_RUNTIME_LIMIT env vars.

Closes #2874
@alex-solovyev alex-solovyev force-pushed the bugfix/t1398.1-process-resource-guard branch from 844cffb to 545701e Compare March 5, 2026 04:29
@github-actions
Copy link

github-actions bot commented Mar 5, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 107 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Thu Mar 5 04:30:02 UTC 2026: Code review monitoring started
Thu Mar 5 04:30:02 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 107

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 107
  • VULNERABILITIES: 0

Generated on: Thu Mar 5 04:30:04 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 5, 2026

@github-actions github-actions bot added the enhancement Auto-created from TODO.md tag label Mar 5, 2026
@alex-solovyev alex-solovyev merged commit bce161d into main Mar 5, 2026
20 checks passed
@alex-solovyev alex-solovyev deleted the bugfix/t1398.1-process-resource-guard branch March 5, 2026 05:09
alex-solovyev added a commit that referenced this pull request Mar 5, 2026
…1402)

Add _sanitize_log_field() helper that strips control characters (ASCII
0x00-0x1F and 0x7F) from untrusted strings before writing to log files.
Applied to cmd_base in guard_child_processes() where process names from
ps output are logged during termination.

Addresses the medium-severity log injection findings from Gemini review
on PR #2881. The two critical findings (grep -v $$ self-exclusion
bypass) were already fixed by prior PRs that rewrote the process guard
to use awk descendant-tree walking.

Closes #2892
marcusquinn pushed a commit that referenced this pull request Mar 5, 2026
…1402)

Add _sanitize_log_field() helper that strips control characters (ASCII
0x00-0x1F and 0x7F) from untrusted strings before writing to log files.
Applied to cmd_base in guard_child_processes() where process names from
ps output are logged during termination.

Addresses the medium-severity log injection findings from Gemini review
on PR #2881. The two critical findings (grep -v $$ self-exclusion
bypass) were already fixed by prior PRs that rewrote the process guard
to use awk descendant-tree walking.

Closes #2892
marcusquinn pushed a commit that referenced this pull request Mar 5, 2026
…1402) (#2908)

Add _sanitize_log_field() helper that strips control characters (ASCII
0x00-0x1F and 0x7F) from untrusted strings before writing to log files.
Applied to cmd_base in guard_child_processes() where process names from
ps output are logged during termination.

Addresses the medium-severity log injection findings from Gemini review
on PR #2881. The two critical findings (grep -v $$ self-exclusion
bypass) were already fixed by prior PRs that rewrote the process guard
to use awk descendant-tree walking.

Closes #2892
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Auto-created from TODO.md tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

t1398.1: Add process resource guard to pulse-wrapper.sh

2 participants