Fix unescaped dots in package name validation regex patterns#26775
Fix unescaped dots in package name validation regex patterns#26775
Conversation
Co-authored-by: TravisEz13 <10873629+TravisEz13@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Tightens package-name validation by fixing regex patterns that previously treated . as “any character”, which could allow malformed package names (e.g., preview@6) to pass validation in release pipelines and packaging tests.
Changes:
- Escaped the dot between suffix label and suffix number (e.g.,
preview.6) in macOS.pkgvalidation. - Escaped the same dot in Linux
.tar.gzvalidation. - Escaped the same dot across multiple artifact validation patterns in the release pipeline template (tar.gz, pkg, msi/zip, deb).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
.pipelines/templates/release-validate-packagenames.yml |
Makes package name validation stricter by escaping . in suffix patterns across multiple artifact types. |
test/packaging/macos/package-validation.tests.ps1 |
Aligns macOS PKG test regex with the corrected dot-escaped suffix format. |
test/packaging/linux/package-validation.tests.ps1 |
Aligns Linux tar.gz validation regex with the corrected dot-escaped suffix format. |
| $message = @() | ||
| Get-ChildItem $(System.ArtifactsDirectory)\* -recurse -include *.zip, *.msi | ForEach-Object { | ||
| if($_.Name -notmatch 'PowerShell-\d+\.\d+\.\d+\-([a-z]*.\d+\-)?win\-(fxdependent|x64|arm64|x86|fxdependentWinDesktop)\.(msi|zip){1}') | ||
| if($_.Name -notmatch 'PowerShell-\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?win\-(fxdependent|x64|arm64|x86|fxdependentWinDesktop)\.(msi|zip){1}') |
There was a problem hiding this comment.
The Windows MSI/ZIP name regex uses ([a-z]*\.\d+\-)?, which allows an empty label before the dot (e.g. -.6-). If only named suffixes like preview.6 are valid, change [a-z]* to [a-z]+ (and consider anchoring with ^...$ to avoid substring matches).
| if($_.Name -notmatch 'PowerShell-\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?win\-(fxdependent|x64|arm64|x86|fxdependentWinDesktop)\.(msi|zip){1}') | |
| if($_.Name -notmatch '^PowerShell-\d+\.\d+\.\d+\-([a-z]+\.\d+\-)?win\-(fxdependent|x64|arm64|x86|fxdependentWinDesktop)\.(msi|zip){1}$') |
| $message = @() | ||
| Get-ChildItem $(System.ArtifactsDirectory)\* -recurse -filter *.deb | ForEach-Object { | ||
| if($_.Name -notmatch 'powershell(-preview|-lts)?_\d+\.\d+\.\d+([\-~][a-z]*.\d+)?-\d\.deb_amd64\.deb') | ||
| if($_.Name -notmatch 'powershell(-preview|-lts)?_\d+\.\d+\.\d+([\-~][a-z]*\.\d+)?-\d\.deb_amd64\.deb') |
There was a problem hiding this comment.
The DEB validation regex uses ([\-~][a-z]*\.\d+)?, which allows an empty label after -/~ (e.g. -.6). If suffixes must be named (like -preview.6), require at least one letter ([a-z]+). Also consider anchoring the pattern (^...$) so only full-filename matches are accepted.
| if($_.Name -notmatch 'powershell(-preview|-lts)?_\d+\.\d+\.\d+([\-~][a-z]*\.\d+)?-\d\.deb_amd64\.deb') | |
| if($_.Name -notmatch '^powershell(-preview|-lts)?_\d+\.\d+\.\d+([\-~][a-z]+\.\d+)?-\d\.deb_amd64\.deb$') |
| # Pattern matches: powershell-7.6.0-preview.6-linux-x64.tar.gz or powershell-7.6.0-linux-x64.tar.gz | ||
| # Also matches various runtime configurations | ||
| if ($package.Name -notmatch 'powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*.\d+\-)?(linux|osx|linux-musl)+\-(x64\-fxdependent|x64|arm32|arm64|x64\-musl-noopt\-fxdependent)\.(tar\.gz)') { | ||
| if ($package.Name -notmatch 'powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?(linux|osx|linux-musl)+\-(x64\-fxdependent|x64|arm32|arm64|x64\-musl-noopt\-fxdependent)\.(tar\.gz)') { |
There was a problem hiding this comment.
The tar.gz regex here isn’t anchored and includes (linux|osx|linux-musl)+, which can match invalid names via substring matches and repeated platform tokens (e.g. linuxlinux). Consider switching to an anchored regex (^...$) and removing the + quantifier so only a single platform token is accepted.
| if ($package.Name -notmatch 'powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?(linux|osx|linux-musl)+\-(x64\-fxdependent|x64|arm32|arm64|x64\-musl-noopt\-fxdependent)\.(tar\.gz)') { | |
| if ($package.Name -notmatch '^powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?(linux|osx|linux-musl)\-(x64\-fxdependent|x64|arm32|arm64|x64\-musl-noopt\-fxdependent)\.tar\.gz$') { |
| # - powershell-7.4.13-rebuild.5-osx-arm64.pkg (Rebuild version) | ||
| # - powershell-lts-7.4.13-osx-arm64.pkg (LTS package) | ||
| $pkgPackageNamePattern = '^powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*.\d+\-)?osx\-(x64|arm64)\.pkg$' | ||
| $pkgPackageNamePattern = '^powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?osx\-(x64|arm64)\.pkg$' |
There was a problem hiding this comment.
([a-z]*\.\d+\-)? allows an empty label before the dot (e.g. -.6-) to match as a “preview/rebuild” suffix. If suffixes must be named (like preview.6/rebuild.5), change [a-z]* to [a-z]+ so malformed names are rejected.
| $pkgPackageNamePattern = '^powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?osx\-(x64|arm64)\.pkg$' | |
| $pkgPackageNamePattern = '^powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]+\.\d+\-)?osx\-(x64|arm64)\.pkg$' |
| $message = @() | ||
| Get-ChildItem $(System.ArtifactsDirectory)\* -recurse -filter *.tar.gz | ForEach-Object { | ||
| if($_.Name -notmatch 'powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*.\d+\-)?(linux|osx|linux-musl)+\-(x64\-fxdependent|x64|arm32|arm64|x64\-musl-noopt\-fxdependent)\.(tar\.gz)') | ||
| if($_.Name -notmatch 'powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?(linux|osx|linux-musl)+\-(x64\-fxdependent|x64|arm32|arm64|x64\-musl-noopt\-fxdependent)\.(tar\.gz)') |
There was a problem hiding this comment.
The tar.gz validation regex uses (linux|osx|linux-musl)+, which allows repeated/concatenated platform tokens (e.g. linuxlinux) to pass. Use a single alternation group without the + quantifier (and consider anchoring the pattern to the full filename) so malformed names can’t match via repetition or substring matches.
| if($_.Name -notmatch 'powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?(linux|osx|linux-musl)+\-(x64\-fxdependent|x64|arm32|arm64|x64\-musl-noopt\-fxdependent)\.(tar\.gz)') | |
| if($_.Name -notmatch '^powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?(linux|osx|linux-musl)\-(x64\-fxdependent|x64|arm32|arm64|x64\-musl-noopt\-fxdependent)\.tar\.gz$') |
| $message = @() | ||
| Get-ChildItem $(System.ArtifactsDirectory)\* -recurse -filter *.pkg | ForEach-Object { | ||
| if($_.Name -notmatch 'powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*.\d+\-)?osx\-(x64|arm64)\.pkg') | ||
| if($_.Name -notmatch 'powershell-(lts-)?\d+\.\d+\.\d+\-([a-z]*\.\d+\-)?osx\-(x64|arm64)\.pkg') |
There was a problem hiding this comment.
This .pkg regex uses ([a-z]*\.\d+\-)?, where [a-z]* permits an empty label (e.g. -.6-) to match as a “suffix”. If the intent is to only allow suffixes like preview.6/rebuild.5, require at least one letter (e.g. [a-z]+) and consider anchoring the pattern (^...$) so extra prefix/suffix text can’t slip through substring matching.
Regex patterns for package name validation used unescaped dots (
.) which match any character, allowing malformed names likepowershell-7.6.0-preview@6-osx-x64.pkgto pass validation.Changes
[a-z]*.→[a-z]*\.) across:.pipelines/templates/release-validate-packagenames.yml(tar.gz, pkg, msi/zip, deb patterns)test/packaging/macos/package-validation.tests.ps1(pkg pattern)test/packaging/linux/package-validation.tests.ps1(tar.gz pattern)Now correctly rejects names with wrong delimiters (e.g.,
preview@6,rebuild-5) while accepting valid suffixes (e.g.,preview.6,rebuild.5).Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.