A stale Flux source URL left my cluster open to repojacking

2026-09-23 Resolved SEV3 flux gitops security

I changed my GitHub username and updated one reference to the old repository URL, but not the one Flux uses to sync the whole cluster. For two months, the cluster only kept working because GitHub redirects renamed accounts. Anyone who registered the old username could have pushed their own manifests and Flux would have applied them. Nobody did, and nothing was changed.

Impact

  • Exposed: full control of the cluster, from 2026-07-26 to 2026-09-23.
  • Actual impact: none. The old username was never registered by anyone else.

Timeline

  • 2026-07-26: GitHub username changed. The URL in the khider.fr HelmRelease is updated, the Flux GitRepository in gotk-sync.yaml is not.
  • 2026-09-23, 00:08: the GitRepository URL is pointed at the new repository.
  • 2026-10-02: Flux is re-bootstrapped against the new repository over SSH.

Root cause

When a GitHub account is renamed, requests to the old URL are redirected to the new one, but only until someone registers the old username. At that point the old URL belongs to them.

The flux-system GitRepository is the root of everything Flux deploys. Its Kustomization has prune: true, and Flux applies changes with cluster-admin rights. A public repository with the same name, branch and path under the old username would have been pulled within minutes. Its contents would have been applied, and anything of mine not in it would have been deleted. The secretRef on the source does not prevent this, since a public repository clones without credentials.

What went wrong

  • The rename was followed by a manual fix of the one reference I remembered, not a search of the repository for the old name.
  • Flux trusted whatever the URL returned. Nothing tied the source to my account or my commits.

Follow-ups

  • Point the Flux GitRepository at the new repository.
  • Re-bootstrap Flux against the new repository with SSH authentication.