The public Engine API accepts caller-supplied RepoDescriptor.Name values and combines each name with TargetRoot without enforcing that the name is one safe path segment or that the final path remains under the requested root.
GitHub repository names supplied by the built-in lister are safe, but gclo.Engine is a public NuGet library. A caller can provide a rooted path, parent traversal, or path separators and cause clone/pull operations outside TargetRoot.
Evidence
The public sync overload accepts an arbitrary descriptor list: gclo.Engine/OrgSyncEngine.cs:49-69.
Repository names are passed to Path.Combine and then cloned or pulled without containment validation: gclo.Engine/OrgSyncEngine.cs:95-114.
RepoDescriptor documents Name as a local folder name but performs no validation: gclo.Engine/RepoDescriptor.cs:3-8.
This finding was independently verified at commit 119ac26804ef93b98a262cb1c0c7a41afe71fde5. It is related to the Engine findings collected in #31, but is tracked separately as a public API trust-boundary bug.
Acceptance criteria
Reject empty names, rooted paths, . and .., directory separators, and any value that is not exactly one safe leaf segment.
Resolve the final target with Path.GetFullPath and verify it remains within the normalized target root before any directory creation or git operation.
Validation behaves consistently across Windows path forms, including drive-rooted and UNC inputs.
Unit tests cover parent traversal, absolute paths, both separator styles, rooted Windows paths, and valid GitHub repository names.
Invalid input fails before creating or modifying anything outside the target root and returns an actionable error.
## Problem
The public Engine API accepts caller-supplied `RepoDescriptor.Name` values and combines each name with `TargetRoot` without enforcing that the name is one safe path segment or that the final path remains under the requested root.
GitHub repository names supplied by the built-in lister are safe, but `gclo.Engine` is a public NuGet library. A caller can provide a rooted path, parent traversal, or path separators and cause clone/pull operations outside `TargetRoot`.
## Evidence
- The public sync overload accepts an arbitrary descriptor list: `gclo.Engine/OrgSyncEngine.cs:49-69`.
- Repository names are passed to `Path.Combine` and then cloned or pulled without containment validation: `gclo.Engine/OrgSyncEngine.cs:95-114`.
- `RepoDescriptor` documents `Name` as a local folder name but performs no validation: `gclo.Engine/RepoDescriptor.cs:3-8`.
This finding was independently verified at commit `119ac26804ef93b98a262cb1c0c7a41afe71fde5`. It is related to the Engine findings collected in #31, but is tracked separately as a public API trust-boundary bug.
## Acceptance criteria
- Reject empty names, rooted paths, `.` and `..`, directory separators, and any value that is not exactly one safe leaf segment.
- Resolve the final target with `Path.GetFullPath` and verify it remains within the normalized target root before any directory creation or git operation.
- Validation behaves consistently across Windows path forms, including drive-rooted and UNC inputs.
- Unit tests cover parent traversal, absolute paths, both separator styles, rooted Windows paths, and valid GitHub repository names.
- Invalid input fails before creating or modifying anything outside the target root and returns an actionable error.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
The public Engine API accepts caller-supplied
RepoDescriptor.Namevalues and combines each name withTargetRootwithout enforcing that the name is one safe path segment or that the final path remains under the requested root.GitHub repository names supplied by the built-in lister are safe, but
gclo.Engineis a public NuGet library. A caller can provide a rooted path, parent traversal, or path separators and cause clone/pull operations outsideTargetRoot.Evidence
gclo.Engine/OrgSyncEngine.cs:49-69.Path.Combineand then cloned or pulled without containment validation:gclo.Engine/OrgSyncEngine.cs:95-114.RepoDescriptordocumentsNameas a local folder name but performs no validation:gclo.Engine/RepoDescriptor.cs:3-8.This finding was independently verified at commit
119ac26804ef93b98a262cb1c0c7a41afe71fde5. It is related to the Engine findings collected in #31, but is tracked separately as a public API trust-boundary bug.Acceptance criteria
.and.., directory separators, and any value that is not exactly one safe leaf segment.Path.GetFullPathand verify it remains within the normalized target root before any directory creation or git operation.