From fddd82704fd3e0bd2312ba92843c9f8c13dcb6ee Mon Sep 17 00:00:00 2001 From: mr-forust Date: Sun, 27 Sep 2026 10:15:43 +0200 Subject: [PATCH] ci: keep pull requests away from the production admission webhooks `kubectl apply --dry-run=server` persists nothing, but it does execute the admission webhooks of the real API server. The validate job runs on pull_request with no branch guard, so anyone able to open a PR could run arbitrary manifest content through cert-manager and Traefik in production. Limit the step to pushes to main. A pull request loses nothing by it: only main is ever deployed, and this job has to complete successfully before the deploy workflow is allowed to start, so a bad CRD is still caught before anything reaches the cluster -- on the push instead of on the PR. The skip is announced rather than silent, so a missing server-side pass does not read as a pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/ci.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index f32cbe3..32a5cb7 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -214,7 +214,25 @@ jobs: # dry-run needs the target namespace to exist, and inactive services are not # deployed. Services being enabled for the first time are still covered by # the JSON-schema pass above. + # + # Main pushes only. `--dry-run=server` persists nothing, but it does execute + # the admission webhooks of the production API server, so anyone able to open + # a pull request would be able to run arbitrary manifest content through + # cert-manager and Traefik. A pull request has nothing to gain from it either: + # only main is ever deployed, and this job runs to completion before the + # deploy workflow is allowed to start, so a bad CRD is still caught before + # anything reaches the cluster -- just on the push rather than on the PR. + - name: Note the server-side check is not running here + if: github.event_name == 'pull_request' || github.ref != 'refs/heads/main' + shell: bash + run: | + echo "::notice::Skipping the server-side dry-run. It executes the cert-manager and" \ + "Traefik admission webhooks against the production API server, so it is limited" \ + "to pushes to main. CRDs are still schema-checked by kubeconform above, and the" \ + "server-side pass still runs on main before the deploy." + - name: Validate active manifests against the live API server + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' shell: bash run: | set -euo pipefail