Skip to content

Protect release tags from moving #45

Open

Description

@AlexHardAtWork

Add a tag ruleset to repo-settings, and apply it to dev-kit

Type: security · Component: scripts/repo-settings.sh

Problem

Consumers resolve dev-kit by tag: DEV_KIT_VERSION in the Makefile, which curls
common.mk, and the flake.nix input. GitHub tags are mutable, and two mechanisms adopt a moved
tag with nobody reading code:

  • renovate-dev-kit-lock resolves the tag to a commit and writes it to flake.lock,
    unattended. The visible diff is a narHash.
  • common.mk is fetched from the tag and -included into make.

dev-kit's flake is the shell every consumer's CI runs in, so a moved tag means code execution in
every job across the org.

check-dev-kit-pins (#44) only detects this, and is itself fetched from the tag it checks.

Fix: the ruleset in repo-settings, applied to dev-kit first

The ruleset is per repository, and repo-settings.sh is how every repo gets one — so this ships
as a helper there and each repo opts in by running the target. dev-kit is where it is urgent,
because its tags are what every consumer resolves; the consumers want it for their own releases
too, which is the follow-up tickets.

{ "name": "protect-release-tags", "target": "tag", "enforcement": "active",
  "conditions": { "ref_name": { "include": ["refs/tags/v*"], "exclude": [] } },
  "rules": [ { "type": "update" }, { "type": "deletion" } ] }

Add it to repo-settings.sh beside the existing protect-main ruleset — same create-or-update
shape, roughly 25 lines, pattern and enforcement as REPO_* variables. dev-kit tracks its own
common.mk from main (DEV_KIT_VERSION := main), so dev-kit gets this as soon as it
merges
, with no release needed.

Prerequisite: dev-kit has no REPO_* block in its Makefile today, so repo-settings is not
yet configured for dev-kit itself. That has to come first.

Not an org-wide ruleset. ~ALL would reach all 25 live repos for the sake of ~5 of ours,
including forks of upstream projects — external-dns-management,
machine-controller-manager-provider-hcloud, gardener-extension-provider-hcloud — where
syncing a fork legitimately moves upstream tags. Same cross-team-agreement principle as the
.github defaults.

No CI breaks: repo-settings.sh is admin-run only — the workflow token cannot manage
rulesets — and the rules are update/deletion, not creation, so every repo's release tooling
keeps tagging normally.

The one behavioural change

A v* tag can no longer be moved or deleted in a repo that has the ruleset. A botched
release is fixed by bumping to the next patch, not by retagging. Decide whether bypass_actors
exempts org admins — it keeps the escape hatch and weakens the guarantee by exactly that much.

Acceptance criteria

  • REPO_* configured for dev-kit, so make repo-settings can run there.
  • make repo-settings creates or updates a tag ruleset; pattern and enforcement are REPO_*
    variables.
  • Moving and deleting an existing v* tag in dev-kit are both refused.
  • A new dev-kit release still tags successfully.
  • A decision recorded on admin bypass.
  • Immutable releases enabled on dev-kit as defence in depth — a toggle; check it is available
    on the plan and fits release-drafter's publish-from-draft flow.
  • dev-kit's README states that release tags are immutable, so consumers know a pinned tag
    cannot change under them.

Out of scope

  • Rolling the ruleset out to consumers. Their own release tags are worth protecting, but it
    is a different goal from this one and each repo decides its own REPO_*. Follow-up tickets
    per repo, after the dev-kit v3 migrations (artifact-conduit#499, apiserver-kit#132,
    ocm-components#106).
  • The common.mk fetch. Immutable tags stop a tag being repointed; publishing a new
    release still executes arbitrary make code in every consumer. Signing or SHA-anchoring that
    fetch is a separate design.
  • check-dev-kit-pins (feat: add check-dev-kit-pins and a flake.lock closure diff #44) stays: it still catches ordinary pin drift, which is how Solar
    ended up split across v2.1.0 and v2.2.0.
  • ocm-kit — left the org, frozen at v0.1.4.

Relations

From review of #44. Prerequisite for installing dev-kit-bot beyond
opendefensecloud/solution-arsenal — that app is what makes the tag-to-commit conversion
unattended. Suggested in opendefensecloud/renovate-config#20's follow-up notes.

Unrelated, noticed while scoping: apiserver-kit's Makefile has two DEV_KIT_VERSION
lines (v2.0.0, v2.1.0). Harmless today, fails check-dev-kit-pins on its v3 adoption. Own
issue.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageIssue that has not been reviewed

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions