From c4049959804253fb950f8baca55149afa3b1fd95 Mon Sep 17 00:00:00 2001 From: Edwin van den Houdt Date: Wed, 22 Jul 2026 09:34:13 +0200 Subject: [PATCH] ci: replace CodeQL with Semgrep (Gitea-compatible SAST) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeQL is GitHub-only — its analyze step uploads SARIF to GitHub's code-scanning API and assumes a GitHub Security tab; this CI runs on Gitea only, so the job could never go green (it had been red since it was added). Replace it with Semgrep OSS, a plain CLI SAST with no account/platform API, which runs fine on Gitea. - Remove the codeql job (+ its security-events permission) and the schedule trigger (it existed only for codeql; semgrep runs on push + PR). - Add a semgrep job: setup-python + `pip install semgrep` + `semgrep scan --config p/default --config p/csharp --metrics=off`. pip-on-runner (not container:) mirrors the other jobs' model; anonymous registry, telemetry off. - Report-only for now (no --error → job stays green): a local dry-run found 27 findings, mostly CI/config policy (unpinned actions, .npmrc), not app-code vulns. WP-30 tracks triaging them + flipping to --error (a blocking gate). Verified locally: `semgrep scan` runs clean (exit 0 without --error, 306 rules / 450 files). CI behaviour confirmable only on the Gitea runner — watch the run. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 48 +++++++------------ .../backlog/WP-30-ci-perf-followups.md | 6 +++ 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e32ad17..496bf95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,11 +5,8 @@ on: branches: [main] tags: ['v*'] pull_request: - # CodeQL runs on main + this weekly cron only (not on PRs) — see the codeql job's `if`. - schedule: - - cron: '0 3 * * 1' # Mondays 03:00 UTC -# Least privilege by default; the CodeQL job widens its own scope locally. +# Least privilege by default. permissions: contents: read @@ -111,38 +108,25 @@ jobs: - run: npx playwright install --with-deps chromium - run: npm run e2e - codeql: - # Static analysis (SAST) for both sides; results appear under the Security tab. - # Off the PR path (slow 2-language matrix) — runs on push-to-main + the weekly - # cron only, so PR feedback isn't bottlenecked on it. - if: github.event_name != 'pull_request' + semgrep: + # SAST for both sides — replaces CodeQL, which is GitHub-only (its analyze step uploads + # SARIF to GitHub's code-scanning API) and can't run on this Gitea instance. Semgrep OSS + # is a plain CLI: no account, no external platform API. Findings print in the job log. + # ponytail: report-only for now (no `--error`, so the job stays green while the initial + # findings are triaged); flip to `--error` to make it a blocking gate. See WP-30. runs-on: ubuntu-latest - timeout-minutes: 20 - permissions: - security-events: write - contents: read - actions: read - strategy: - fail-fast: false - matrix: - language: [javascript-typescript, csharp] + timeout-minutes: 15 steps: - uses: actions/checkout@v4 - - if: matrix.language == 'csharp' - uses: actions/setup-dotnet@v4 + - uses: actions/setup-python@v5 with: - dotnet-version: 10.0.x - - if: matrix.language == 'csharp' - uses: actions/cache@v4 - with: - path: ~/.nuget/packages - key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj') }} - restore-keys: nuget-${{ runner.os }}- - - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - - uses: github/codeql-action/autobuild@v3 - - uses: github/codeql-action/analyze@v3 + python-version: '3.12' + cache: pip + - run: pip install semgrep + # p/default = curated cross-language security (covers JS/TS); p/csharp = the backend. + # Anonymous registry fetch; --metrics=off disables telemetry (not `auto`, which uploads + # project metadata). + - run: semgrep scan --config p/default --config p/csharp --metrics=off api-client-drift: # The committed typed client must match the backend OpenAPI doc. diff --git a/docs/project/backlog/WP-30-ci-perf-followups.md b/docs/project/backlog/WP-30-ci-perf-followups.md index f5238ed..9f552c0 100644 --- a/docs/project/backlog/WP-30-ci-perf-followups.md +++ b/docs/project/backlog/WP-30-ci-perf-followups.md @@ -44,6 +44,12 @@ runner image, set on the act_runner host). 5. **Lean deployable backend image** (optional, not for the dev demo): multi-stage prod build on `mcr.microsoft.com/dotnet/aspnet:10.0` (~220 MB) in a separate `docker-compose.prod.yml`. The dev `docker-compose.yml` keeps the SDK image because `dotnet run` hot-reload needs it. +6. **Semgrep: triage findings + make it blocking.** Semgrep replaced CodeQL (GitHub-only, couldn't + run on Gitea) and currently runs **report-only** — a local dry-run found 27 findings, mostly + CI/config policy (unpinned GitHub Actions in `ci.yml`, `.npmrc` min-release-age) rather than + app-code vulns. Triage them (fix or `# nosemgrep`/`.semgrepignore` the noise; consider a + tighter ruleset than `p/default` if the GitHub-Actions-policy rules aren't wanted), then add + `--error` to `semgrep scan` so it's a real gate. ## Acceptance criteria