Repository navigation
Stop Crediting an until read Loop as Bounded in the Guard - #2161
Conversation
An exhausted or empty input makes `read` fail forever, which keeps an `until` condition false forever, so requirement 7's read bound now holds for a `while` loop only. The docstring and README requirement 7 say so, and the self-test carries the `until read ... < f` case as a deny. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The requirement 7 flowchart still routed an `until read ... < f` loop to allow, which disagreed with the guard and with the paragraph above it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Repository: ptr727/ProjectTemplate/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 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. Comment |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The change is minimal and fully verified — the keyword gate correctly denies until read loops, the sole caller passes the loop keyword, and a matching self-test plus consistent documentation updates accompany it.
Review effort: Balanced
Findings: None
What changed in this PR
This PR fixes a security-hardening defect in the Claude Code gh-write-guard.py hook that enforces requirement 7 (deny unbounded shell wait loops). Previously, the "read bound" exemption credited any loop whose condition began with read over a descriptor-0 redirect as bounded, without distinguishing while from until. For an until loop, an exhausted or empty input makes read fail forever, keeping the condition false forever, so the loop never exits — the exact opposite of a bound. The guard now grants the read-bound exemption only to while loops, and the accompanying documentation is corrected to match.
Changes:
_reads_its_inputgains akeywordparameter and returnsFalsefor any loop keyword other thanwhile; the single caller now passes the loop keyword token.- A new self-test case denies
until read l; do sleep 30; done < f, beside the existingwhile readallow case, so reverting the keyword check fails the test. - The docstring, README requirement 7 paragraph, and the flowchart node are updated to state the bound holds only for a
whileloop.
I verified that the caller passes the actual loop keyword (tok = toks[i] where _opens_loop is true), that _reads_its_input has no other callers, that the new tuple lands in _WAIT_CASES (exercised through classify), and that the arithmetic-for path is unaffected since its condition never begins with read. The prose changes are ASCII-clean with no banned issue references or mid-sentence semicolons. A related pre-existing weakness in the while read path was correctly filed separately rather than expanded into this change.
| File | Description |
|---|---|
| host-setup/agent-safety/claude/gh-write-guard.py | Adds while-only gate to _reads_its_input, updates the caller to pass the loop keyword, refreshes the docstring, and adds an until read deny self-test. |
| host-setup/agent-safety/README.md | Corrects requirement 7 prose and the flowchart node to state the read bound applies only to a while loop. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #2161 +/- ##
==========================================
Coverage ? 56.47%
==========================================
Files ? 16
Lines ? 7455
Branches ? 0
==========================================
Hits ? 4210
Misses ? 3245
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
… a Second Site's Verify Token Pair, With Fifteen More (#2175) ## Summary Promotes develop to main, carrying these pull requests: - [#2172](#2172) Accept Letters in Recorded Names in the Charset Rule and Prose Gate - [#2173](#2173) Forward a Second Site's Token Pair to the Deploy-Site Verify Hook - [#2169](#2169) Record HomeAutomation-Config's Merge-Bot and Gate Adoption in the Rollout Tracking - [#2164](#2164) Pass --no-project to the Pre-Commit Snippet's uv run Hooks - [#2161](#2161) Stop Crediting an until read Loop as Bounded in the Guard - [#2158](#2158) Drop the Path Argument From the Pre-Commit Snippet's Mypy Swap - [#2155](#2155) Reword the Canonical CRLF-Exception Comments for a Carrier's Own Pin - [#2153](#2153) End the Guard's Stdin Redirect Scan at a Reserved Word - [#2150](#2150) Describe the Pip Form Consistently Across python-codestyle - [#2144](#2144) Read the Run Id From the Runner's Environment in the Artifact-Cleanup Steps - [#2142](#2142) Diff a Merge Commit's Prose Against Its Merged-In Parent in the Pre-Commit Hook - [#2136](#2136) Qualify the Local Review Skill's Merge-Base Command to Match the Engine - [#2134](#2134) Quote the Bare Placeholder in skills_install.py's Usage Block - [#2132](#2132) Write the Hub-Checkout Reach Into the session-handoff Chain Commands - [#2130](#2130) Name the Missing build-system Condition in the Lint-Only Profile Bullet - [#2128](#2128) Skip a Blockquoted List Marker in the Prose Gate's Semicolon Rule - [#2119](#2119) State the Three Gaps D4.7's Supersede-and-Dispatch Step Leaves Open ## Closes Closes #2100 Closes #2031 Closes #1779 Closes #2148 Closes #1633 Closes #1188 Closes #1992 Closes #2032 Closes #2052 Closes #1481 Closes #2116 Closes #2107 Closes #2097 Closes #1512 Closes #2026 Closes #2101 Closes #2009 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Deployment verification can now check a second site using its own optional authentication token. * **Documentation** * Updated writing guidance to preserve the spelling and diacritics of recorded names. * Clarified Python project setup, formatting and testing guidance, and line-ending rules. * Expanded deployment and publishing guidance, including scenarios where publishing runs overlap. * **Bug Fixes** * Prose checks now handle quoted lists and tables more accurately, and merge checks avoid flagging comments brought in from the merged branch. * Improved checks for shell loops that read redirected input. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Requirement 7's
readbound credited a loop whose condition is a leadingreadover a descriptor-0 redirect without tellingwhilefromuntil. Foruntil, an exhausted or empty input failsreadforever, which keeps the condition false forever, so the loop never ends._reads_its_inputnow takes the loop keyword and credits the bound for awhileloop only. Thewhilecase is unchanged.until read l; do sleep 30; done < fas a deny beside the existingwhile read l; do sleep 30; done < fallow. Reverting the keyword check makes that case fail._reads_its_input's docstring, the requirement 7 paragraph inhost-setup/agent-safety/README.md, and its flowchart node now say the bound holds for awhileloop.A local strict review pass also found pre-existing ways a
while readcondition can fail to exhaust its input, filed as #2160 rather than fixed here.Closes on promotion: #1633
🤖 Generated with Claude Code