From 551d182f4d0e5ec2b131cfd44efc1fa02d5633dc Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 3 Aug 2026 12:33:54 -0700 Subject: [PATCH 1/2] improvement(ci): move CodeQL off default setup onto Blacksmith Default setup pinned every scan to a 4-vCPU GitHub-hosted runner with no cancel-in-progress: PR scans ran 30-125 min and re-ran on every push (#6183 burned six overlapping runs). None of that is reachable from the settings UI, so the config moves into the repo. - Blacksmith 8-vCPU via the same CI_PROVIDER escape hatch as ci.yml - cancel-in-progress scoped to pull_request so push/schedule scans finish - push to main + PR to main/staging + nightly safety net - paths filter so doc-only PRs skip the run entirely - paths-ignore config drops tests/mocks/fixtures: 12,716 -> 11,128 files - languages: javascript-typescript + actions; python dropped (7 files in tree) Default setup has been disabled; the two cannot both be active. --- .github/codeql/codeql-config.yml | 27 ++++++++++ .github/workflows/codeql.yml | 91 ++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 .github/codeql/codeql-config.yml create mode 100644 .github/workflows/codeql.yml diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 00000000000..fd640a261cf --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,27 @@ +name: Sim CodeQL config + +# Trims the extraction surface. CodeQL parses every matching file into a +# database before a single query runs, and that phase dominates runtime on a +# ~12.7k-file JS/TS tree. Test and fixture code is not attacker-reachable, so +# excluding it costs no real coverage. +# +# paths-ignore applies to analysis. The workflow's `on.pull_request.paths` +# filter is separate and decides whether the run happens at all. +paths-ignore: + - '**/*.test.ts' + - '**/*.test.tsx' + - '**/*.test.js' + - '**/*.spec.ts' + - '**/*.spec.tsx' + - '**/__tests__/**' + - '**/__mocks__/**' + - '**/__fixtures__/**' + - '**/test/**' + - '**/tests/**' + - '**/testing/**' + - '**/e2e/**' + - '**/*.d.ts' + - '**/node_modules/**' + - '**/dist/**' + - '**/.next/**' + - 'apps/docs/content/**' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..130d9ecede6 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,91 @@ +name: CodeQL + +# Advanced setup, replacing the repo-settings "default setup". +# +# Default setup pinned every scan to a 4-vCPU GitHub-hosted runner with no +# cancel-in-progress, which put PR scans at 30-125 min and re-ran them on every +# push (PR #6183 burned six overlapping runs). None of that is configurable from +# the settings UI, so the config moves into the repo. +# +# Before enabling this, disable default setup or the two will both run: +# gh api -X PATCH repos/:owner/:repo/code-scanning/default-setup -f state=not-configured +# +# The runs-on expression is the same CI_PROVIDER escape hatch as ci.yml and must +# change together with it. + +on: + # Pushes to main are infrequent (merges only), so a full scan per push is + # affordable and is what GitHub recommends pairing with the PR trigger: + # "Scanning code when someone pushes a change, and whenever a pull request is + # created, prevents developers from introducing new vulnerabilities." + push: + branches: [main] + pull_request: + branches: [main, staging] + # Draft PRs are excluded via the job-level `if`, not here: `types` would + # also have to re-list the default event types to keep synchronize working. + paths: + - '**/*.ts' + - '**/*.tsx' + - '**/*.js' + - '**/*.jsx' + - '**/*.mjs' + - '**/*.cjs' + - '.github/workflows/**' + - '.github/actions/**' + - '.github/codeql/**' + schedule: + # Safety net behind the push trigger, and the thing that keeps the + # default-branch alert view fresh when main is quiet. Only fires once this + # file is on the default branch — schedule events ignore other branches. + - cron: '17 8 * * *' + workflow_dispatch: + +# Scheduled main scans must run to completion — only PR pushes supersede. +concurrency: + group: codeql-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +permissions: + contents: read + +jobs: + analyze: + name: Analyze ${{ matrix.language }} + runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-8vcpu-ubuntu-2404' || 'ubuntu-latest' }} + timeout-minutes: 60 + if: github.event.pull_request.draft != true + permissions: + security-events: write + contents: read + actions: read + + strategy: + fail-fast: false + matrix: + # One entry covers both JS and TS — `javascript`, `typescript` and + # `javascript-typescript` all resolve to the same extractor + # (github/codeql-action src/languages/builtin.json), so the three + # entries default setup listed were one analysis, not three. + # `javascript-typescript` is the documented spelling. Python dropped: + # 7 files in the tree. + language: [javascript-typescript, actions] + + steps: + - name: Checkout repository + uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 + with: + persist-credentials: false + + - name: Initialize CodeQL + uses: github/codeql-action/init@18420e3271f74589575af831a523c833acda327f # codeql-bundle-v2.26.2 + with: + languages: ${{ matrix.language }} + config-file: ./.github/codeql/codeql-config.yml + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@18420e3271f74589575af831a523c833acda327f # codeql-bundle-v2.26.2 + env: + NODE_OPTIONS: --max-old-space-size=8192 + with: + category: /language:${{ matrix.language }} From e29086b23f6d64057580cceed5a66ab24fad2946 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 3 Aug 2026 12:44:57 -0700 Subject: [PATCH 2/2] fix(ci): restore CodeQL coverage of the data-drain test route MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review round 1. - Drop the '**/test/**' and '**/tests/**' globs. A `test` directory is a routable Next.js path segment, and those globs excluded apps/sim/app/api/organizations/[id]/data-drains/[drainId]/test/route.ts — a POST handler that authorizes, decrypts destination credentials and makes an outbound request. CodeQL paths-ignore has no `!` negation to carve it back out, and the globs only covered 76 of 12,716 files. - Add `ready_for_review` to the pull_request activity types. It is not a default type, so a PR opened as a draft and later marked ready was skipped by the draft guard and never rescanned until the next push. --- .github/codeql/codeql-config.yml | 12 +++++++++--- .github/workflows/codeql.yml | 7 +++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index fd640a261cf..b8e56f708d9 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -16,10 +16,16 @@ paths-ignore: - '**/__tests__/**' - '**/__mocks__/**' - '**/__fixtures__/**' - - '**/test/**' - - '**/tests/**' - - '**/testing/**' - '**/e2e/**' + # Deliberately no '**/test/**' or '**/tests/**'. A directory named `test` is a + # routable Next.js path segment, not necessarily test code: those globs + # excluded the real endpoint + # apps/sim/app/api/organizations/[id]/data-drains/[drainId]/test/route.ts, + # which authorizes, decrypts destination credentials, and makes an outbound + # request. CodeQL's paths-ignore has no `!` negation to carve it back out + # ("The filter pattern characters ?, +, [, ], and ! are not supported and will + # be matched literally"), and the globs only covered 76 of 12,716 files, so + # the naming convention above is the safer filter. - '**/*.d.ts' - '**/node_modules/**' - '**/dist/**' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 130d9ecede6..51b709d5330 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -22,8 +22,11 @@ on: branches: [main] pull_request: branches: [main, staging] - # Draft PRs are excluded via the job-level `if`, not here: `types` would - # also have to re-list the default event types to keep synchronize working. + # `ready_for_review` is not a default activity type, so it has to be listed + # alongside the defaults it replaces. Without it, a PR opened as a draft and + # then marked ready is skipped by the job-level draft guard and never + # rescanned until the next push. + types: [opened, synchronize, reopened, ready_for_review] paths: - '**/*.ts' - '**/*.tsx'