fix(signing): require active tag rulesets for release tags in the verifier
User description
Summary
Part of #1206. Step 1 of 2: make the release-tag verifier independent of github.ref_protected.
Both release workflows require github.ref_protected == true on the v* tag push. GitHub's variables reference says that is true when rulesets apply to the ref, but community reports (discussion 142985, discussion 66588) describe it staying false for tag pushes. If that is the case on the real tag push, both verifier jobs are skipped and nothing publishes. Because release-tags-immutable has no bypass actor, the pushed tag could then not be deleted or moved, so the version would be unusable. No v* tag was created to probe this.
What changes
verifyRemoteTagnow reads the repository's active tag rulesets (GET /rulesets?targets=tag, then one detail per active repository ruleset) and requires thatcreation,update,deletionandnon_fast_forwardare all covered forrefs/tags/<tag>. Coverage may be split across rulesets.- It fails closed on: no ruleset, a disabled or evaluate-only ruleset, a non-tag target, an inherited ruleset whose rules cannot be read, a different include pattern, an excluded ref, unknown pattern syntax (a pattern outside a safe subset never matches an include and always counts as an exclude), a failed list request, and a list of 100 or more entries that may be truncated.
- The check runs after the signature and protected-main ancestry checks and before the final tag ref re-read.
refPatternMatchesis exported and tested directly.
Evidence
- Live, read-only and unauthenticated: the real signed tag
v1.29.2passes the fullverifyRemoteTagpath, including the new ruleset coverage forrefs/tags/v1.29.2. This also shows the check works with a low-privilege caller, which is what the workflow token is. verifyRemoteTag(44) andsigning(72) tests pass locally, including 11 new rejection cases, a split-ruleset acceptance case and the pattern table.
Known limit
The API hides bypass_actors from callers without admin rights, so this check cannot prove that no actor can bypass release-tags-immutable. That stays a setting a maintainer verifies with an authenticated read (done: no bypass actors on ruleset 26812769). It is documented in docs/VERIFIED-SIGNING.md.
Next step
The workflows pin the verifier to 147470682b62, so they do not run this code yet. After this merges, a second small PR moves the pin in docker.yml, tauri-build.yml, scripts/release-security-gate.mjs and the gate test to the resulting protected-main commit and drops the github.ref_protected condition. Until then the workflows keep their current conditions.
Release boundary
No tag, GitHub Release, registry push or Vercel mutation. This PR does not authorize v1.29.3.
Summary by Sourcery
Harden release-tag verification by validating complete active ruleset protection directly through the GitHub rulesets API.
Bug Fixes:
- Require release-tag verification to confirm that active repository tag rulesets fully protect the pushed tag, rather than relying on unreliable protected-ref status.
Enhancements:
- Fail closed when tag ruleset coverage is missing, inactive, unsupported, excluded, unreadable, or potentially truncated, while allowing protection to be distributed across multiple rulesets.
Documentation:
- Document active tag ruleset verification and the limitation that bypass-actor validation requires an authenticated maintainer check.
Tests:
- Add coverage for ruleset protection scenarios, safe ref-pattern matching, split ruleset coverage, and fail-closed rejection cases.
Chores:
- Update the changelog and README test-count metrics.
Summary by cubic
Makes release-tag verification depend on active tag rulesets read directly from the rulesets API rather than github.ref_protected, which community reports say stays false for tag pushes. The verifier now requires creation, update, deletion and non-fast-forward coverage for the pushed ref and fails closed on disabled, evaluate-only, mis-targeted, excluded, or unreadable rulesets.
- Coverage may be split across several active repository rulesets.
bypass_actorsremains visible only to admins, so the no-bypass guarantee stays a maintainer's authenticated-read check, documented rather than enforced by the verifier.- Pattern syntax outside a supported safe subset, including double stars, is treated as unknown and never matches, so it cannot be used to grant or deny coverage. Matching uses an iterative glob so no pattern text reaches a regular expression.
Rollout
- Workflows still pin the verifier to the prior commit, so release behavior is unchanged; a follow-up moves the pin and drops the
github.ref_protectedcondition.
CodeAnt-AI Description
Require active tag rulesets for release verification
What Changed
- Release-tag verification now checks active rulesets for the pushed tag instead of relying on GitHub’s protected-ref status.
- Verification requires creation, update, deletion, and non-fast-forward protection; coverage can be split across rulesets. Missing, unreadable, or unsupported protection fails verification.
Impact
✅ Rejects release tags without full protection
✅ Accepts protection split across active rulesets
✅ Verifies tag protection when GitHub’s protected-ref status is unreliable
💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
@codeant-ai ask: Your question here
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
@codeant-ai ask: Can you suggest a safer alternative to storing this secret?
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
@codeant-ai: Your feedback here
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
@codeant-ai: Do not flag unused imports.
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
@codeant-ai: review
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.
Summary by CodeRabbit
- Bug Fixes
- Release tag verification now checks active repository rulesets to confirm the pushed tag is covered by rules for creation, updates, deletion, and non-fast-forward changes. Verification also requires the ruleset information to be fully retrieved.
- Documentation
- Updated the verified-signing policy to describe the tag ruleset checks and relevant visibility limitations.
- Refreshed the README’s reported test count.