fix(build): verify the PSGallery source before installing from it - #51
Conversation
A repository named PSGallery is not necessarily the PowerShell Gallery. build.ps1 accepted any existing registration on the strength of its name and then installed every dependency in build.depend.psd1 from it. A registration pointing at another SourceLocation -- a mirror, a proxy, or something deliberately placed -- would have supplied all of them silently. The source URL is now compared against the canonical one and a mismatch throws. Found by review on SrrDBAutomationToolkit and already shipped there and in ScheduledTasksManager. build.ps1 is byte-identical across the remaining four repositories, and this change is a pure ten-line addition to each with nothing else touched. Unsigned at the author's request -- 1Password is unavailable this session. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G1CarQG8VibNFxw4cN53Zs
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe bootstrap script validates the registered ChangesBootstrap validation
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk:⚪ Minimal · up to The build now rejects a PSGallery registration that points to an unexpected source, preventing dependencies from being installed from an unintended repository; no actionable merge-blocking risk remains after normal checks and review. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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.
Pull request overview
This PR hardens the build bootstrap process by ensuring that the PSGallery repository name actually points to the official PowerShell Gallery endpoint before any build dependencies are installed from it. This prevents a locally-registered repository named PSGallery (but backed by a different URL) from silently supplying all modules listed in build.depend.psd1.
Changes:
- Adds a strict
SourceLocationverification for thePSGalleryPSRepository during-Bootstrap. - Throws with a clear error message if
PSGalleryis registered to an unexpected URL. - Ensures dependency installation only proceeds when the repository identity (URL) matches the expected PowerShell Gallery endpoint.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Review pointed out that -ne is case-insensitive, so a source location differing only in case would pass the check, and suggested -cne. -cne would be wrong in the other direction. Host names are case-insensitive by definition, so a strict comparison rejects https://WWW.PowerShellGallery.com/api/v2 -- which is the real gallery. The identifying part is the host, and a repository standing in for the gallery would differ there, not in casing. The source location is now parsed and its scheme and host compared, which accepts any casing of the genuine host and rejects a different one. Unparseable values are rejected too, where the previous string comparison would have thrown on a null SourceLocation instead. Verified: https://www.powershellgallery.com/api/v2 accepted https://WWW.PowerShellGallery.com/api/V2 accepted https://evil.example.com/api/v2 rejected not-a-uri rejected Unsigned at the author's request -- 1Password is unavailable this session. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G1CarQG8VibNFxw4cN53Zs
tablackburn
commented
Aug 18, 2026
@coderabbitai full review |
|
Review noted that comparing scheme and host alone accepts https://www.powershellgallery.com:444/api/v2. A non-default port on the same name reaches a different listener, so that is a real gap. Port is now compared too; [Uri] supplies 443 for https when none is given, so the canonical URL and an explicit :443 both match. The path is still deliberately not compared, and the comment now says why: the gallery serves both /api/v2 and /api/v3, and any path on the genuine host is still the genuine host. Host and port are the trust boundary, so pinning the path would only add a false rejection for a legitimate registration. The three stacked comment blocks this accumulated over successive reviews are consolidated into one. Verified: https://www.powershellgallery.com/api/v2 accepted https://WWW.PowerShellGallery.com/api/V2 accepted https://www.powershellgallery.com:443/api/v2 accepted https://www.powershellgallery.com/other-path accepted https://www.powershellgallery.com:444/api/v2 rejected http://www.powershellgallery.com/api/v2 rejected https://evil.example.com/api/v2 rejected not-a-uri rejected Unsigned at the author's request -- 1Password is unavailable this session. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G1CarQG8VibNFxw4cN53Zs
Uh oh!
There was an error while loading. Please reload this page.
A repository named
PSGalleryis not necessarily the PowerShell Gallery.build.ps1accepted any existing registration on the strength of its name and then installed every dependency inbuild.depend.psd1from it. A registration pointing elsewhere — a mirror, a proxy, or something deliberately placed — would have supplied all of them silently.What it checks
The source location is parsed and compared on scheme, host and port:
https://www.powershellgallery.com/api/v2https://WWW.PowerShellGallery.com/api/V2https://www.powershellgallery.com:443/api/v2https://www.powershellgallery.com/other-pathhttps://www.powershellgallery.com:444/api/v2http://www.powershellgallery.com/api/v2https://evil.example.com/api/v2not-a-uriNot a string comparison.
-neis case-insensitive, so a differently cased value slipped through;-cnewould be wrong in the other direction, rejectinghttps://WWW.PowerShellGallery.com/api/v2, which is the real gallery.Path deliberately not compared. The gallery serves both
/api/v2and/api/v3, and any path on the genuine host is still the genuine host. Host and port are the trust boundary; pinning the path would only add a false rejection.Provenance
Found by review on SrrDBAutomationToolkit #36 and already shipped there and in ScheduledTasksManager. This propagates it to the remaining four, whose
build.ps1files were byte-identical (sha1 d6e2a118) — verified by diff before copying.Behavioural note
This throws rather than warning. A build environment with
PSGalleryregistered against a different host or port now fails instead of quietly installing from it. Verified against a normal registration: JsmOperations 118 passed, YouTubeMusicPS 323 passed, and the rendered template 30 passed, with the check inert.No
CHANGELOG.mdentry: build tooling, not user-facing.🤖 Generated with Claude Code
https://claude.ai/code/session_01G1CarQG8VibNFxw4cN53Zs
Summary by CodeRabbit