Skip to content

t1398.2: Harden ShellCheck invocation to prevent exponential expansion#2885

Merged
alex-solovyev merged 1 commit intomainfrom
bugfix/harden-shellcheck-invocation
Mar 5, 2026
Merged

t1398.2: Harden ShellCheck invocation to prevent exponential expansion#2885
alex-solovyev merged 1 commit intomainfrom
bugfix/harden-shellcheck-invocation

Conversation

@alex-solovyev
Copy link
Collaborator

Summary

  • Harden ShellCheck invocations in pulse-wrapper.sh and linters-local.sh to prevent the exponential source expansion that caused the March 3 kernel panic (5.7 GB RSS, 88% CPU, 35+ min runtime)
  • Add --norc flag to pulse-wrapper.sh quality sweep to ignore .shellcheckrc's source-path=SCRIPTDIR directive
  • Add ulimit -v 1GB per-subprocess memory cap as defense-in-depth in both scripts

Changes

pulse-wrapper.sh (quality sweep)

  • --norc: Prevents .shellcheckrc from being read, which sets source-path=SCRIPTDIR and could cause implicit source following
  • No -x/--external-sources: Already the case, now explicitly documented
  • ulimit -v 1048576: Caps virtual memory to 1 GB per shellcheck subprocess
  • Updated guard_child_processes() comment: Clarifies this is a secondary defense, not primary

linters-local.sh (interactive linting)

  • ulimit -v 1048576: Added to both timeout and portable-fallback paths
  • Keeps -x -P SCRIPTDIR: Interactive use benefits from source resolution; per-file timeout + ulimit provide sufficient protection
  • Updated comments: Documents the defense-in-depth strategy

.shellcheckrc

  • Warning comment: Documents the exponential expansion risk when source-path=SCRIPTDIR is combined with --external-sources

Defense-in-Depth Layers

Layer pulse-wrapper.sh (headless) linters-local.sh (interactive)
External sources No -x (never follows sources) -x -P SCRIPTDIR (restricted)
RC file --norc (ignores .shellcheckrc) Uses .shellcheckrc (intentional)
Per-file timeout 30s via timeout/gtimeout 30s via timeout/gtimeout
Memory cap ulimit -v 1GB per subprocess ulimit -v 1GB per subprocess
Process guard guard_child_processes() every 60s N/A (interactive)

Closes #2875

…1398.2)

- pulse-wrapper.sh quality sweep: add --norc to ignore .shellcheckrc
  source-path=SCRIPTDIR, preventing implicit source following; add
  ulimit -v 1GB per subprocess to cap virtual memory
- linters-local.sh: wrap shellcheck in subshell with ulimit -v 1GB
  for both timeout and portable-fallback paths
- .shellcheckrc: add warning comment about exponential expansion risk
  when combined with -x/--external-sources
- Update guard_child_processes() comment to reflect defense-in-depth
  layering (process guard is secondary, not primary defense)

Root cause: shellcheck --external-sources with source-path=SCRIPTDIR
follows source directives across 100+ scripts, causing exponential
expansion (5.7 GB RSS, 88% CPU, 35+ min — March 3 kernel panic).

Closes #2875
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

Warning

Rate limit exceeded

@alex-solovyev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 17 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 78a321c2-c10a-465e-8c71-13252e037e08

📥 Commits

Reviewing files that changed from the base of the PR and between 9d30fe7 and 160dbb8.

📒 Files selected for processing (3)
  • .agents/scripts/linters-local.sh
  • .agents/scripts/pulse-wrapper.sh
  • .shellcheckrc
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/harden-shellcheck-invocation

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 significantly enhances the robustness of ShellCheck invocations within the system's linting scripts. The primary goal is to prevent resource exhaustion and system instability caused by runaway ShellCheck processes, particularly those involving recursive source expansions. The changes introduce multiple layers of protection, ensuring that both automated quality sweeps and interactive linting sessions operate within defined resource limits.

Highlights

  • ShellCheck Hardening: Implemented measures in pulse-wrapper.sh and linters-local.sh to prevent exponential source expansion during ShellCheck invocations, addressing a past kernel panic.
  • pulse-wrapper.sh Updates: Added --norc flag to ignore .shellcheckrc and explicitly documented the absence of -x/--external-sources to prevent implicit source following.
  • Memory Cap: Introduced ulimit -v 1GB per-subprocess memory cap in both pulse-wrapper.sh and linters-local.sh as a defense-in-depth mechanism.
  • linters-local.sh Specifics: Maintained -x -P SCRIPTDIR for interactive use, relying on per-file timeout and ulimit for protection, and updated comments to reflect the defense strategy.
  • .shellcheckrc Warning: Added a warning comment to .shellcheckrc explaining the risk of source-path=SCRIPTDIR when combined with --external-sources.
Changelog
  • .agents/scripts/linters-local.sh
    • Updated comments to reflect the hardened ShellCheck invocation strategy and defense-in-depth layers.
    • Added ulimit -v 1048576 (1GB) to cap virtual memory for ShellCheck subprocesses in both the timeout_cmd and portable fallback paths.
    • Clarified that -x is retained for interactive use due to per-file timeout and ulimit guards.
  • .agents/scripts/pulse-wrapper.sh
    • Updated comments for guard_child_processes() to clarify its role as a secondary defense mechanism.
    • Added extensive comments detailing the hardening layers for ShellCheck invocation, including the use of --norc and the absence of -x.
    • Implemented ulimit -v 1048576 (1GB) for ShellCheck subprocesses during the quality sweep.
    • Added --norc flag to the ShellCheck command to ignore .shellcheckrc.
  • .shellcheckrc
    • Added a warning comment explaining the risks of source-path=SCRIPTDIR when combined with --external-sources and advising on mitigation strategies for different invocation types.
Activity
  • No human activity has been recorded on this pull request yet.
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.

@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:47:45 UTC 2026: Code review monitoring started
Thu Mar 5 03:47:45 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:47:47 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 5, 2026

@alex-solovyev alex-solovyev merged commit 0184605 into main Mar 5, 2026
18 of 19 checks passed
@alex-solovyev alex-solovyev deleted the bugfix/harden-shellcheck-invocation branch March 5, 2026 03:49
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 hardens the ShellCheck invocations in pulse-wrapper.sh and linters-local.sh to prevent the previously observed exponential source expansion and resulting system instability. The use of ulimit, --norc, and per-file timeouts creates a robust, multi-layered defense. The accompanying comments and documentation updates are clear and very helpful for future maintenance.

I have one suggestion in pulse-wrapper.sh to improve debuggability by not suppressing stderr, in line with the project's general guidelines.

# ulimit -v in subshell to cap RSS per shellcheck process.
result=$(
ulimit -v 1048576 2>/dev/null || true
$sc_timeout_cmd shellcheck --norc -f gcc "$shfile" 2>/dev/null || true

Choose a reason for hiding this comment

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

medium

The use of 2>/dev/null here suppresses all standard error output from the shellcheck command. This can hide important diagnostic information if the command fails for reasons other than finding linting issues (e.g., 'command not found', file permission errors). This practice goes against the repository's general rule to avoid blanket error suppression to aid in debugging. The || true is sufficient to prevent script termination on a non-zero exit code. Removing the redirection will allow legitimate system errors to be visible while still capturing the intended shellcheck output.

Suggested change
$sc_timeout_cmd shellcheck --norc -f gcc "$shfile" 2>/dev/null || true
$sc_timeout_cmd shellcheck --norc -f gcc "$shfile" || 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.

@marcusquinn
Copy link
Owner

Follow-up: root cause removed in PR #2939

This PR hardened shellcheck invocations with --norc, timeouts, and ulimit. PR #2939 removes the root cause (source-path=SCRIPTDIR from .shellcheckrc) and disables SC1091 globally. All defense-in-depth layers from this PR remain active.

Upstream hazard note: The bash-language-server still hardcodes --external-sources — other opencode/shellcheck users with source-path in their .shellcheckrc will hit the same issue. See anomalyco/opencode#16209.

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.

t1398.2: Harden ShellCheck invocation

2 participants