Repository navigation
Refuse a Windows Drive Component Anywhere in a Tree Path - #2247
Conversation
escapes_repo_root in spec/validate.py matched a drive letter only at the start of a value, and relative_root in scripts/carry.py matched none, so a value such as real/C:x passed both. On Windows, joining that component discards everything joined before it, which sends either tool's component walk outside the root. Both now refuse a drive-letter spelling in any component before the walk runs, with a test in each suite that fails with the fix reverted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Windows reads any character followed by a colon as a drive, not only a letter, so real/1:x still discarded the root in both walks. carry.py also accepted a component starting with a backslash, which resets the walk to the drive root. Both now ask PureWindowsPath for the drive (and in carry.py the root too) rather than matching a regex. 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 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #2247 +/- ##
==========================================
Coverage ? 56.69%
==========================================
Files ? 16
Lines ? 7495
Branches ? 0
==========================================
Hits ? 4249
Misses ? 3246
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:
|
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The change tightens security-adjacent path validation across two fleet tools and the shared spec, so final human review is warranted despite the change being small and well-tested.
Review effort: Balanced
Findings: None
What changed in this PR
This PR hardens path validation in two fleet tools so a Windows drive-shaped component is refused anywhere in a declared tree path, not only at the start. On Windows, joining a drive-relative component such as C:x onto a path discards everything joined before it, so a value like real/C:x could previously slip past validation and, in spec/validate.py, trigger an uncaught ValueError crash in the downstream symlink walk. The change closes that gap in both the spec validator and the carrier, keeping their refusal behavior aligned.
Changes:
escapes_repo_rootinspec/validate.pynow refuses a component wheneverPureWindowsPath(part).driveis non-empty (any character followed by a colon), replacing the start-only^[A-Za-z]:regex.relative_rootinscripts/carry.pyrefuses a component wheneverPureWindowsPath(part).anchoris non-empty, covering both a drive and a leading-backslash root, before the path is joined or walked.- Added tests in both suites asserting these values are refused; both fail if the fix is reverted.
| File | Description |
|---|---|
spec/validate.py |
Refuse a drive-shaped component in any position of a tree path and reuse the parsed parts, preventing a later crash. |
scripts/carry.py |
Reject a Windows drive or root in any component before joining/walking the path. |
tests/test_spec_validate.py |
Extend the drive-letter refusal test with mid-path and digit-colon components. |
tests/test_carry.py |
Add a test covering drive, root, and backslash components refused by relative_root. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
## Summary Promotes develop to main, carrying the pull requests below, each already reviewed and merged into develop. - [#2203](#2203): Strip every heredoc body a line opens in the wait-loop rule. - [#2216](#2216): Point the charset-unknown message at where a tier is classified. - [#2218](#2218): Name the leftover old tree when the Bash loader cannot remove it. - [#2227](#2227): End the guard's stdin redirect scan at a trailing comment. - [#2230](#2230): Tell apart the causes a labels payload is refused for. - [#2232](#2232): Correct the task names and pointers in the Python tasks snippet header. - [#2234](#2234): Drop the stale private-repository note from PhotoCleaner's registry entry. - [#2237](#2237): State the bootstrap's archive live channel in two skills. - [#2239](#2239): Stop the promotion count on a failed fetch in backlog-burndown. - [#2241](#2241): Render the include walk once per `build_dist.py --check` run. - [#2243](#2243): Have the tree check call `escapes_repo_root` and refuse a symlinked component. - [#2247](#2247): Refuse a Windows drive component anywhere in a tree path. - [#2222](#2222): Tick the adopted repos in the merge-bot and gate rollout stages. - [#2121](#2121): Refuse a dangling remote-tracking target in `local_review`. - [#2249](#2249): Ignore a quoted separator when the guard finds a loop's `done`. Closes #2112 Closes #2171 Closes #1790 Closes #2152 Closes #1372 Closes #2149 Closes #1082 Closes #1772 Closes #1310 Closes #1379 Closes #1452 Closes #2244 Closes #2168 Closes #2106 Closes #2207 🤖 Generated with [Claude Code](https://claude.com/claude-code)
escapes_repo_rootinspec/validate.pymatched a Windows drive only at the start of a value, andrelative_rootinscripts/carry.pymatched none. Both tools walk a tree path one component at a time withcurrent /= part, and on Windows joining a component that carries a drive, such asC:x, discards everything joined before it. A value such asreal/C:xpassed both.escapes_repo_rootnow refuses a component wheneverPureWindowsPath(part).driveis non-empty. That is wider than a letter, since Windows reads any character followed by a colon as a drive (1:x,_:x).relative_rootrefuses a component wheneverPureWindowsPath(part).anchoris non-empty, which also covers a leading backslash. That spelling resets the walk to the drive root in the same way, andescapes_repo_rootalready refuses it.The local review pass also found that
relative_rootstill accepts a backslash in the middle of a component. That gap predates this change and is filed as #2246.Closes on promotion: #2244
🤖 Generated with Claude Code