Skip to content

ci(security): add CodeQL code scanning (SAST)#1535

Closed
pedrofuentes wants to merge 1 commit into
mainfrom
ci/codeql-scanning
Closed

ci(security): add CodeQL code scanning (SAST)#1535
pedrofuentes wants to merge 1 commit into
mainfrom
ci/codeql-scanning

Conversation

@pedrofuentes

Copy link
Copy Markdown
Owner

What

Adds the repository's first real SAST workflow: GitHub CodeQL code scanning for the JavaScript/TypeScript codebase. Previously the repo only had OpenSSF Scorecard posture (no actual static analysis).

.github/workflows/codeql.yml:

  • Triggers: push to main, pull_request to main, and a weekly schedule (30 6 * * 1, Mondays 06:30 UTC).
  • Least-privilege permissions: top-level contents: read; the analyze job elevates only actions: read + security-events: write (scoped to the one job that uploads results).
  • Language: CodeQL's combined javascript-typescript with build-mode: none (JS/TS needs no build).
  • Queries: security-extended for broader security coverage.
  • Concurrency group cancels superseded runs (matches deploy-pages.yml style).

SHA-pinning (repo policy)

Every uses: is pinned to a full 40-char commit SHA with a # vX.Y.Z comment (resolved via gh api), matching the existing ci.yml/scorecard.yml convention and satisfying Scorecard PinnedDependencies:

Action SHA Version
actions/checkout 9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 v7.0.0 (reuses existing repo pin)
github/codeql-action/init 8aad20d150bbac5944a9f9d289da16a4b0d87c1e v4.36.2
github/codeql-action/analyze 8aad20d150bbac5944a9f9d289da16a4b0d87c1e v4.36.2

CodeQL Action v4 is the current major recommended for github.com and is compatible with this repo's Node 24 baseline.

Validation

  • yaml-lint passed and structural parse (16/16 semantic assertions) passed
  • All 3 uses: confirmed SHA-pinned (40-hex) + version comment
  • pnpm typecheck green, pnpm lint green (0 warnings), pnpm test green (3606 passed, 1 skipped), prettier --check clean

Scope

Only .github/workflows/codeql.yml added. No other workflow/source/dependency changes. Default setup was not enabled via API (workflow file only). CI-config addition is TDD-exempt; suite stays green.

Add a CodeQL SAST workflow analyzing the combined javascript-typescript
language on pushes to main, pull requests to main, and a weekly schedule.

- Least-privilege permissions: contents:read at the top level; the analyze
  job elevates only actions:read and security-events:write to upload results.
- All actions SHA-pinned to 40-char commits with version comments per repo
  policy (Scorecard PinnedDependencies).
- build-mode: none (CodeQL JS/TS needs no build) and queries:security-extended
  for broader security coverage.
- Concurrency group cancels superseded runs.

Co-authored-by: Copilot <175574315+pedrofuentes@users.noreply.github.com>
@pedrofuentes

Copy link
Copy Markdown
Owner Author

Status: REJECTED

Sentinel Review Report

Ref: ci/codeql-scanning → main
Report ID: SENTINEL-1535-f92b426
Reviewed SHA: f92b426
Sentinel ruleset: v1
Reviewed at: 2026-06-22T13:15:35-07:00
Mode: standard
Review depth: Tier 2 (full)
Required action: FIX_AND_REINVOKE

Phase 1 — TDD / Test Evidence

PR is a single ci(security) commit changing only .github/workflows/codeql.yml (+53). CI-config → TDD-exempt (choreography checks 1–4 and coverage check 6 do not apply; no behavior-bearing source code). Check 5 (suite stays green) still applies.

  • Tests exist & meaningful: N/A — ci-exempt (no behavior code)
  • Test-first history verified: N/A — ci-exempt (single ci(security) commit)
  • Full suite green on SHA: ❌ — The repo's existing test/lint/coverage/smoke checks are GREEN on f92b426 (no-code diff: zero source/test/build-config files changed — ⚠️ no-code; unit-suite run skipped). However, the workflow this PR introduces fails on the reviewed SHA: run 27979086525 ("CodeQL", event pull_request, headSha f92b426) FAILED at "Perform CodeQL Analysis". This failure is the basis for the 🔴 below.
  • Coverage: N/A — ci-only change; threshold not re-evaluated

Phase 1.5 — Fast-path Evaluation

🔴 count: 1 | LOC: 53 (≤150: Y) | Security paths: Y (CI/CD pipeline — sensitive surface) | New deps: Y (3 pinned third-party Actions added) | Commit types qualify: N (ci ∉ {fix,refactor,docs,test,style,chore})
→ Fast-path eligible: NO → Phase 2 (multiple criteria unmet; 🔴 present)

Phase 2 — Execution Log

Selective dispatch for a ci commit → A1, A2, E, F. B/C/D logged N/A (exempt) per SENTINEL §Selective dispatch (chore/build/ci → A1,A2,E,F).

Dim Tool Call Agent ID / Ref Status
A1 task(agent_type=general-purpose, name=dim-a1) dim-a1 (sync/inline result)
A2 task(agent_type=general-purpose, name=dim-a2) dim-a2 (sync/inline result)
B N/A (exempt — ci) ⏭️
C N/A (exempt — ci) ⏭️
D N/A (exempt — ci) ⏭️
E task(agent_type=general-purpose, name=dim-e) dim-e (sync/inline result)
F task(agent_type=general-purpose, name=dim-f) dim-f (sync/inline result)

Platform note: dimension sub-agents were dispatched as discrete task tool calls returning results inline (no separate persistent agent ID surfaced); distinct dimension refs recorded above.

Findings

  • 🔴 CRITICAL: 1
  • 🟡 IMPORTANT: 0 new / 0 known
  • 🟢 MINOR: 0

Details (ordered by severity)

  1. [🔴 CRITICAL] Advanced CodeQL workflow conflicts with the repo's enabled CodeQL default setup — analysis upload fails on every run — .github/workflows/codeql.yml:50-53
    • Evidence (workflow step):
      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
      
    • Evidence (CI on reviewed SHA f92b426, run 27979086525 "CodeQL" / event pull_request, job "Analyze (javascript-typescript)"):
      ##[error]Code Scanning could not process the submitted SARIF file:
      CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled
      
    • Corroboration: a separate run 27979084553 ("CodeQL", event dynamic) analyzing languages actions + javascript-typescript PASSES — this is GitHub's CodeQL default setup, which is enabled at the repo level. GitHub forbids an advanced configuration from uploading results while default setup is enabled for the same repo/languages.
    • Impact: The newly added workflow fails on every push/PR to main and on the weekly schedule, producing a permanently-red check and uploading no results. The PR's stated goal — working CodeQL SAST — is not achieved; the only CodeQL coverage remains the pre-existing default setup. This is incorrect behavior under normal usage and a direct conflict with existing repo CodeQL configuration (contradicting the "does not conflict with existing workflows" requirement).
    • Reachability: Triggered on normal repo activity (push/PR to main, weekly cron) — no attacker needed; it fails deterministically.
    • Remediation (do NOT fix 🟡/🟢; this 🔴 must be resolved before re-invoke): resolve the default-vs-advanced conflict, then re-run to confirm the "Perform CodeQL Analysis" upload succeeds. Either —
      • Option A: Disable CodeQL default setup (repo → Settings → Code security → Code scanning → switch from Default to Advanced), making this workflow the sole CodeQL config; or
      • Option B: Drop this advanced workflow and instead tune queries/schedule via default setup.
        Note: toggling repo code-scanning setup is a repository-settings/admin action (human-performed), not a code change in this PR.
    • Fixability: 🧠 judgment-needed (config/ownership decision) + 👤 human-required (repo security settings)

Verifications that PASSED (not findings — recorded for auditability)

  • SHA-pinning (repo policy): all three uses: are full 40-char commit SHAs with matching # vX.Y.Z comments, verified via gh api:
    • actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 — SHA == v7.0.0 commit (exact).
    • github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 — annotated tag v4.36.2 (1a818fd5…) dereferences to this commit (exact).
    • github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 — same exact match (init/analyze correctly share the codeql-action tag SHA).
  • Least privilege: top-level permissions: { contents: read } (no top-level writes); security-events: write scoped to the analyze job, alongside actions: read + contents: read. ✅
  • Correctness: triggers (push+PR to main, weekly cron 30 6 * * 1), languages: javascript-typescript, build-mode: none (valid for JS/TS), checkout→init→analyze order, ubuntu-latest, concurrency group ${{ github.workflow }}-${{ github.ref }}. GitHub parsed and executed all steps (run 27979086525 ran init + analysis to completion) — authoritative proof the YAML and step config are valid; the sole failure is the SARIF upload conflict, not a syntax/config error.
  • No injection / no secrets: no run: shell steps; no secrets.*; the only ${{ }} expressions are github.workflow, github.ref, matrix.language, matrix.build-mode (no untrusted github.event.* data). Dim A2 & Dim F: No findings.
  • No file-level workflow conflict: the only other concurrency group: in .github/workflows/ is "pages" (deploy-pages.yml); scorecard.yml uses codeql-action/upload-sarif (a different sub-action) — no collision with this file. (The conflict is with the repo-level default-setup setting, not another workflow file.)

Follow-ups & Actions

  • REJECTED → FIX_AND_REINVOKE: resolve the 🔴 default-vs-advanced CodeQL conflict (Option A or B above), confirm the workflow's "Perform CodeQL Analysis" step succeeds on the branch HEAD, then re-invoke Sentinel with this Report ID + the fix delta.
  • No 🟡/🟢 to file.
  • ⚠️ Do NOT merge: a 🔴 is open and the introduced required check is red on the reviewed SHA.

Decision rationale

  • The workflow is well-authored on every dimension Sentinel checks individually (SHA-pinning exact, least-privilege correct, triggers/build-mode/order valid, no injection/secrets) — A2/E/F returned No findings.
  • BUT it is fundamentally incompatible with the repository's current state: CodeQL default setup is already enabled, so this advanced configuration's analyze upload fails deterministically on f92b426 with "CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled."
  • That is incorrect behavior under normal usage + a permanently-failing check + a conflict with existing CodeQL configuration → 🔴 CRITICAL (never downgradable).
  • Any 🔴 ⇒ REJECTED (SHA-bound to f92b4264f66d04dca2aad5e86a13558723367c53).

@pedrofuentes

Copy link
Copy Markdown
Owner Author

Closing: Sentinel review (Report SENTINEL-1535-f92b426) found this advanced CodeQL workflow conflicts with the repo's already-enabled CodeQL default setup — GitHub refuses SARIF uploads from an advanced config while default setup is on, so the check fails deterministically. CodeQL SAST is already active via default setup; this workflow is redundant. Keeping default setup. (To switch to advanced/security-extended later, disable default setup in repo Settings → Code security, then re-open.)

@pedrofuentes pedrofuentes deleted the ci/codeql-scanning branch June 22, 2026 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant