Protected packages: Allow standalone wildcard in protection rules
-
Please check this box if this contribution uses AI-generated content (including content generated by GitLab Duo features) as outlined in the GitLab DCO & CLA. As a benefit of being a GitLab Community Contributor, you receive complimentary access to GitLab Duo.
What does this MR do and why?
Enables PyPI and NPM package protection rules to accept a standalone *
wildcard pattern that matches all packages, bringing them in line with tag and branch protection behavior.
Previously, both NPM and PyPI protection regex patterns required at least one structural character due to the +
quantifier, preventing the use of *
alone to protect all packages in a project. This created an inconsistency where administrators could not apply blanket protection to all packages.
Technical implementation:
- Uses regex alternation
(?:\*|...)
to match either*
OR the existing package name pattern with wildcards - Maintains backward compatibility with all existing patterns
- SQL matching via ILIKE already supports
*
conversion to%
- No model or database changes required
This consistent behavior allows administrators to protect all packages with a single rule, then add exceptions as needed.
References
- Closes #573365
- Related to #323971 (closed) (wildcard package protection request)
- Related to #3497 (closed) (original protected packages feature)
Screenshots or screen recordings
N/A - Backend regex validation change only
It is now possible to store only a stand-alone wildcard character (*
) in the protected_packages
settings UI.
How to set up and validate locally
Quick validation (regex and API)
- Start your GitLab development environment
- Test via Rails console:
# Verify the regex accepts standalone wildcard Gitlab::Regex::Packages::Protection::Rules.protection_rules_npm_package_name_pattern_regex.match?('*') # => true # Test PyPI as well Gitlab::Regex::Packages::Protection::Rules.protection_rules_pypi_package_name_pattern_regex.match?('*') # => true # Verify SQL matching works project = Project.find_by(name: "Your Project") rule = Packages::Protection::Rule.create!( project: project, package_type: :npm, package_name_pattern: '*', minimum_access_level_for_push: :maintainer ) # Should match any package name project.package_protection_rules.for_package_name('@scope/any-package').include?(rule) # => true
- Test via REST API:
curl -X POST "http://localhost:3000/api/v4/projects/123/protected_packages" \ -H "PRIVATE-TOKEN: your-token" \ -H "Content-Type: application/json" \ -d '{ "package_name_pattern": "*", "package_type": "npm", "minimum_access_level_for_push": "maintainer" }'
- Test via Web UI:
- Go to http://gdk.local:3000/flightjs/Flight/-/settings/packages_and_registries
- Create a package protection rule for pypi package with a standalone wildcard
End-to-end validation (PyPI package push)
-
Create a protection rule with standalone wildcard:
project = Project.find_by(name: "Your Project") Packages::Protection::Rule.create!( project: project, package_name_pattern: '*', # Standalone wildcard - protects ALL packages package_type: :pypi, minimum_access_level_for_push: :maintainer )
-
Prepare a PyPI package for testing:
- Create a directory with
pyproject.toml
- Set package name to any name (e.g.,
"test-package"
) - Configure
.pypirc
for your local GitLab registry:[distutils] index-servers = gdk [gitlab_gdk_test] repository = http://gdk.local:3000/api/v4/projects/<project-id>/packages/pypi username = <your-username> password = <your-personal-access-token>
- Create a directory with
-
Build and attempt to push the package as a developer (below maintainer):
rm -rf dist/* && python3 -m build && python3 -m twine upload --verbose --repository gdk dist/*
-
Verify protection enforcement:
- The push should be blocked with an error (any package name is now protected)
- Try pushing as a maintainer or owner - it should succeed
- This demonstrates the wildcard
*
pattern protects all packages
-
Verify existing patterns still work (e.g.,
@scope/package-*
)
MR acceptance checklist
Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
MR Checklist (@gerardo-navarro)
-
Changelog entry added, if necessary -
Documentation created/updated via this MR -
Documentation reviewed by technical writer or follow-up review issue created -
Tests added for this feature/bug -
Tested in all supported browsers -
Conforms to the code review guidelines -
Conforms to the style guides -
Conforms to the javascript style guides -
Conforms to the database guides -
Conforms to the merge request performance guidelines -
Backend-only change with comprehensive test coverage (unit, API, GraphQL) -
No breaking changes - maintains backward compatibility with all existing patterns -
Follows established GitLab patterns for regex-based validation