Skip to content

Read the Local Instruction File Only When It Is a Regular File - #2428

Merged
ptr727 merged 4 commits into
developfrom
feature/local-file-regular-only
Oct 6, 2026
Merged

ptr727 merged 4 commits into
developfrom
feature/local-file-regular-only

Conversation

@ptr727

@ptr727 ptr727 commented Oct 6, 2026

Copy link
Copy Markdown
Owner

Summary

This fixes the finding Copilot flagged on promotion PR #2425 as "previously missed". read_local_instructions checked the local instruction file with lstat and then read it directly. A FIFO or a character device at that path blocked the read forever, which hung both the install and --report.

  • A new read_regular_file() opens the path once and judges the open descriptor. It opens with O_RDONLY|O_NONBLOCK and checks the descriptor with fstat and S_ISREG, so a FIFO or a device returns None without blocking. The check and the read are one operation, so nothing can swap the path between them.

  • The descriptor is closed in a finally on every path. An intermediate version leaked one per directory read, because fdopen raised without closing what it was handed.

  • Refusal messages:

    Local path Message
    Not a regular file (a FIFO, a device, a directory) "is not a regular file"
    A dangling link "is a link that leads to nothing"
    A file deleted between the probe and the open "no longer exists"
    Any other open failure "cannot be read"

    The same message appears on Python 3.11, 3.13 and 3.14. An is_file() check would have differed on 3.14, which swallows every OSError.

  • The FIFO cases run with a bound, so a regression fails the test rather than hanging the suite. The report case installs first and then asserts the refusal.

The same FIFO gap exists, from before this change, at settings.json and the stamp. It's recorded on #2426, with read_regular_file() as the shape to reuse.

Refs #2423

Verification

  • python3 -m unittest test_install: 123 tests OK on 3.13 and on 3.14. The edge cases also pass on 3.11.
  • The local strict review ran 3 rounds: 6 findings, then 2, then none.

🤖 Generated with Claude Code

ptr727 and others added 3 commits October 5, 2026 17:40
A FIFO or device at the local instruction path passed the lstat check
and then blocked the read, hanging both the install and --report. Only
a regular file is read now, anything else stops the run with nothing
changed, and the stamp reader skips a stamp that is not a regular file
for the same reason.

Refs #2423

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An is_file() check before the read left a window to swap the path and
gave a different message on Python 3.14, where is_file() swallows every
OSError. read_regular_file() opens once with O_NONBLOCK and checks the
descriptor with fstat, so a FIFO or device returns None without
blocking on every version. The stamp guard is dropped, since the stamp
is read and written unguarded elsewhere, and the FIFO cases run bounded
so a regression fails rather than hangs.

Refs #2423

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
os.fdopen raised on a directory without closing the descriptor it was
handed, so read_regular_file leaked one per directory read. It now
judges and reads the raw descriptor and closes it in a finally, which
also lets a directory reach the regular-file check. A file deleted
between the lstat and the open is now said to no longer exist, keeping
"a link that leads to nothing" for an actual link.

Refs #2423

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727 ptr727 added the comments Permits the comment lines the pull request adds or edits, which the prose gate otherwise refuses label Oct 6, 2026
Copilot AI lite review requested due to automatic review settings October 6, 2026 00:55
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Repository: ptr727/ProjectTemplate/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 828b199d-afe1-4b3a-ba2d-c0bd6e7a1275
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@codecov

codecov Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 58.47%. Comparing base (c24dd93) to head (c272731).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #2428   +/-   ##
========================================
  Coverage    58.47%   58.47%           
========================================
  Files           16       16           
  Lines         8062     8062           
========================================
  Hits          4714     4714           
  Misses        3348     3348           
Flag Coverage Δ
python-3.13 58.47% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Dangling links through non-directory path components need consistent classification before approval.

Review effort: Lite
Findings: 1 Low severity

Open (1)
What changed in this PR

Updates the Claude host-safety installer to safely read only regular local instruction files without blocking on FIFOs or devices.

Changes:

  • Adds descriptor-based, nonblocking reads with guaranteed cleanup.
  • Adds FIFO, report, and descriptor-leak regression coverage.
  • Documents regular-file validation and refusal behavior.
File Reviewed changes
host-setup/​agent-safety/​claude/​install.py Implements safe regular-file reads; requires consistent dangling-link handling and comment cleanup.
host-setup/​agent-safety/​claude/​test_install.py Adds bounded FIFO and descriptor-cleanup tests; updates an outdated test docstring.
host-setup/​agent-safety/​claude/​README.md Documents regular-file validation and refusal behavior.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread host-setup/agent-safety/claude/install.py Outdated
Refs #2423

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Oct 6, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head c272731e872cf1e0f873757e7b84f50a4d93b202, the content this pull request carries at that commit against develop, and it recorded 0 findings.

@ptr727
ptr727 merged commit c23a2a7 into develop Oct 6, 2026
12 checks passed
@ptr727
ptr727 deleted the feature/local-file-regular-only branch October 6, 2026 01:03
ptr727 added a commit that referenced this pull request Oct 6, 2026
## Summary

Promotes `develop` to `main` with four pull requests, each already
reviewed and merged into `develop`:

- [#2424](#2424) Render
the Whole Global CLAUDE.md and Back Up a Hand Edit.
- The host-safety installer now owns all of `~/.claude/CLAUDE.md`. It
renders a header, the two existing blocks, and a shared host-local file,
`agent-fleet/local.md`.
- It replaces an earlier render silently. A file edited by hand, or one
written before this change, is copied to a timestamped `.bak` first.
- `merge-and-release` step 7 now also runs this kit's `--report`, so a
release flags a stale host.
- [#2427](#2427) Render
CLAUDE.md First and Let the Real Write Be the Check, the fix for this
PR's Copilot finding.
- [#2428](#2428) Read the
Local Instruction File Only When It Is a Regular File, the fix for this
PR's previously-missed Copilot finding.
- [#2429](#2429) Refuse a
Local Instruction Path Whose Parent Is a File, the fix for this PR's
third-round Copilot finding.

On a host's next install, the existing `CLAUDE.md` is backed up and
replaced. Anything host-specific moves into the local file.

Closes #2423

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comments Permits the comment lines the pull request adds or edits, which the prose gate otherwise refuses

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants