Repository navigation
Community catalog workflows: make tag-pinned download_url a MUST and reject releases/latest/ #4185
Description
Activity
github-actions commented
on Aug 18, 2026 on Aug 18, 2026 – with GitHub ActionsContributorMore actionsBug assessment — catalog-latest-url-bypass: Valid · severity high
Bug Assessment: Community catalog workflows accept floating
releases/latestdownload URL- Slug:
catalog-latest-url-bypass - Created: 2026-08-18T18:39:39Z
- Source: issue Community catalog workflows: make tag-pinned download_url a MUST and reject
releases/latest/#4185 - Verdict: valid
- Severity: high
Report (summarized)
Reporter mnriem identifies that the three community-catalog agentic workflows use advisory ("should follow the pattern") rather than mandatory language for the
download_urlformat. In PR #4183, an autonomous run replaced a tag-pinned URL with a floatingreleases/latest/download/...alias; validation passed because it only confirmed HTTP 200 and the existence of a matching release — not that the URL is pinned to the submitted version tag. This is a catalog integrity / reproducibility hole: the recorded"version"field would become a lie as the author publishes future releases.Symptom
An autonomous catalog-workflow run accepts a
download_urlcontainingreleases/latest/(e.g..../releases/latest/download/speckit-superpowers-bridge.zip) even though such a URL is not pinned to the submitted version tag and will silently resolve to future releases. Expected behavior: any URL whose path containsreleases/latest/is rejected outright, regardless of HTTP status.Reproduction
- Open or craft a community-extension/bundle/preset issue whose
download_urluses thereleases/latest/download/path instead of a tag-pinned URL. - Trigger the relevant
add-community-extension,add-community-bundle, oradd-community-presetagentic workflow. - Observe validation passes (HTTP 200 check ✓, release-existence check ✓) even though the URL is floating.
Suspected Code Paths
.github/workflows/add-community-extension.md:113–116— step 2d uses "should follow the pattern" (advisory); no explicit rejection rule forreleases/latest/; no check that the URL's embedded tag matches the submitted version..github/workflows/add-community-preset.md:164–168— identical soft wording ("should follow the pattern") in step 2e; same gap..github/workflows/add-community-bundle.md:121–125— step 2c uses stronger wording ("must be") and already verifies the tag corresponds to the submitted version, but does not explicitly forbidreleases/latest/as a path.
Root Cause Hypothesis
The validation steps in the extension and preset workflows use advisory language ("should") that an LLM agent can rationalize past. Even the bundle workflow's harder language does not enumerate
releases/latest/as a forbidden pattern. The URL-format check only validates structure loosely and the HTTP-200 / release-existence checks are orthogonal to URL pinning — so a floating URL sails through all three gates. Confidence: high (confirmed by reading the workflow files and the incident in PR #4183).Proposed Remediation
Preferred: Harden all three workflow files in three coordinated changes:
- Language: Replace "should follow the pattern" with "MUST follow one of the accepted tag-pinned patterns" in
add-community-extension.md(line 113) andadd-community-preset.md(line 164). Alignadd-community-bundle.mdto the same explicit wording. - Reject
releases/latest/: Add an explicit rule in the validation step of each workflow: "If thedownload_urlpath containsreleases/latest/, reject with an explanation — this URL is floating and not acceptable." This should be a hard failure before the HTTP check. - Tag-version match: Add a check that the version segment embedded in the URL (
/download/v1.2.0/or/tags/v1.2.0.zip) matches the submittedversionfield (1.2.0). The bundle workflow already partially does this; extension and preset workflows do not.
Alternatives:
- Introduce a shared validation checklist document that all three workflows reference, so the rule is defined once and kept in sync — reduces drift risk but requires a refactor of the workflow files.
Files likely to change:
.github/workflows/add-community-extension.md.github/workflows/add-community-bundle.md.github/workflows/add-community-preset.md
Tests to add or update:
- Add test cases to the community catalog skill/workflow tests (if any exist) that assert a
releases/latest/download/...URL is rejected. - Add a test that a URL whose embedded tag does not match the submitted version is also rejected.
Risks & Considerations
- Low blast radius for the fix itself: changes are agentic workflow instructions (Markdown), not shipped code — no API breakage, no migrations, no runtime risk.
- Existing catalog entries are unaffected: the remediation only tightens future submissions; existing entries with correct tag-pinned URLs are fine.
- Agent behavior is probabilistic: even with "MUST" language, LLM agents can occasionally deviate. A deterministic script-based URL validator (outside the agent prompt) would be a stronger long-term guard, but is out of scope for this issue.
- Pattern matching edge cases: some repositories use tags without the
vprefix (e.g.1.2.0vsv1.2.0). The tag-version match check should tolerate both forms, consistent with how the bundle workflow already handles it (line 124:`vX.Y.Z` or `X.Y.Z`).
Open Questions
- None blocking the fix. The report is complete and the affected lines are confirmed in the codebase.
Posted on behalf of @mnriem by GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Generated by 🐛 Assess Bug from Labeled Issue for issue #4185 · 87.9 AIC · ⌖ 11.1 AIC · ⊞ 34.1K · ◷
- Slug:
- added a commit that references this issue
on Sep 10, 2026 - added a commit that references this issue
on Sep 10, 2026 - added a commit that references this issue
on Sep 11, 2026
Problem
The community-catalog agentic workflows only softly require a version-pinned
download_url. Step 2d currently says the URL "should follow the pattern" — advisory language an autonomous run can rationalize around.This surfaced in PR #4183 (update
speckit-superpowers-bridgeto v1.2.0), where the run switched the URL to a floating "latest" alias and validation passed it:…/releases/latest/download/…is neither of the two accepted tag-pinned patterns. It resolves to whatever the newest release happens to be, not to the<tag>(v1.2.0) recorded in the entry — so the catalog would keep serving the author's future releases under the pinned"version": "1.2.0"record. That's an integrity/reproducibility hole and breaks the convention (all existing catalogdownload_urls are tag-pinned; none usereleases/latest).The run passed validation because the checks only confirmed the URL returns HTTP 200 and that a v1.2.0 release exists — neither verifies the URL is pinned to the
v1.2.0tag.Affected workflows
Same soft wording appears in all three community-catalog workflows:
.github/workflows/add-community-extension.md:110.github/workflows/add-community-bundle.md:123.github/workflows/add-community-preset.md:164Proposed changes
download_urlrequirement in all three workflows.download_urlwhose path containsreleases/latest/fails validation, even if it returns HTTP 200.<tag>segment matches the submittedv<version>(not just that a release exists and a URL 200s).Accepted URL patterns (unchanged)
https://github.com/<owner>/<repo>/archive/refs/tags/v<version>.ziphttps://github.com/<owner>/<repo>/releases/download/<tag>/<asset>.zipContext