Skip to content

Community catalog workflows: make tag-pinned download_url a MUST and reject releases/latest/ #4185

Description

@mnriem

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-bridge to v1.2.0), where the run switched the URL to a floating "latest" alias and validation passed it:

- .../releases/download/v1.1.0/speckit-superpowers-bridge-v1.1.0.zip   (tag-pinned)
+ .../releases/latest/download/speckit-superpowers-bridge.zip          (floating "latest")

…/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 catalog download_urls are tag-pinned; none use releases/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.0 tag.

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:164

Proposed changes

  1. Change "should follow the pattern" → MUST for the tag-pinned download_url requirement in all three workflows.
  2. Add an explicit rejection rule: a download_url whose path contains releases/latest/ fails validation, even if it returns HTTP 200.
  3. Strengthen the release check to verify the URL's <tag> segment matches the submitted v<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>.zip
  • https://github.com/<owner>/<repo>/releases/download/<tag>/<asset>.zip

Context

Activity

  1. github-actions commented on Aug 18, 2026

    @github-actions
    Contributor

    Bug assessment — catalog-latest-url-bypass: Valid · severity high


    Bug Assessment: Community catalog workflows accept floating releases/latest download URL

    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_url format. In PR #4183, an autonomous run replaced a tag-pinned URL with a floating releases/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_url containing releases/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 contains releases/latest/ is rejected outright, regardless of HTTP status.

    Reproduction

    1. Open or craft a community-extension/bundle/preset issue whose download_url uses the releases/latest/download/ path instead of a tag-pinned URL.
    2. Trigger the relevant add-community-extension, add-community-bundle, or add-community-preset agentic workflow.
    3. 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 for releases/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 forbid releases/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:

    1. Language: Replace "should follow the pattern" with "MUST follow one of the accepted tag-pinned patterns" in add-community-extension.md (line 113) and add-community-preset.md (line 164). Align add-community-bundle.md to the same explicit wording.
    2. Reject releases/latest/: Add an explicit rule in the validation step of each workflow: "If the download_url path contains releases/latest/, reject with an explanation — this URL is floating and not acceptable." This should be a hard failure before the HTTP check.
    3. 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 submitted version field (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 v prefix (e.g. 1.2.0 vs v1.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 · ◷

  2. Shaurya2k06 commented on Aug 18, 2026

    @Shaurya2k06
    Contributor

    I'd like to take this. Could you assign #4185 to me?
    cc @mnriem

    I plan to follow the preferred remediation: harden the three community-catalog workflows so tag-pinned download_url is a MUST, reject releases/latest/ before the HTTP check, and require the URL tag to match the submitted version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions