Skip to content

CodeQL analyses the viewer as built, and the workflows run with least privilege - #402

Merged
RyeMutt merged 4 commits into
developfrom
rye/gha-codeql
Oct 4, 2026
Merged

RyeMutt merged 4 commits into
developfrom
rye/gha-codeql

Conversation

@RyeMutt

@RyeMutt RyeMutt commented Oct 4, 2026 •

Copy link
Copy Markdown
Member

Description

Proper CodeQL support, least-privilege workflow permissions, and the defects a review of build.yaml turned up. Three commits:

1. CI builds name their grid agni, not "agni" with its quotes (fix, can be cherry-picked to release branches)
The configure step passed -DAL_GRID:STRING="\"$VIEWER_GRID\"". Every build log shows Grid "agni". Since the install rules became the package manifest (388db40), that quoted name fails the agni check in newview/CMakeLists.txt. As a result every CI build ships a settings_install.xml with CmdLineGridChoice set to "agni". The viewer then reports an unknown grid at startup and skips the user's last grid (CurrentGrid) and their saved start location.

2. Pull requests read the vcpkg cache in R2 and no longer write it (security)
Same-repository PRs were on the writer keys in readwrite mode, a temporary cache population test. That let unreviewed code put packages in the cache that release builds use. PRs are back on VCPKG_R2_READ_* in read mode. Those keys passed the cache's preflight in the PR builds of 2026-09-20.

3. CodeQL analyses the viewer as built, and the workflows run with least privilege

  • CodeQL (codeql.yaml, codeql/codeql-config.yaml):
    • Default setup scans C/C++ without building it: no vcpkg header resolves, and each run takes about 2h45m. This workflow traces a real build instead, on Linux and on Windows, using the security-extended queries. Python and the workflows themselves are scanned without a build.
    • CMake configure runs before tracing starts, so vcpkg ports stay out of the database. The build tree sits outside the checkout, so their headers stay out of the alerts.
    • MSBuild is told not to reuse worker processes, so Windows compiles aren't missed. Precompiled headers stay on, as in the build: the tree doesn't compile without them (llstring.h uses std::strlen with no <cstring>).
    • The Linux scan keeps default setup's category, so existing alerts and dismissals carry over.
  • Shared setup (actions/setup-build): one place for the apt/brew packages, Python tools, vcpkg bootstrap, R2 cache setup and Rust cache, used by the build and CodeQL. The Rust cache was keyed on a Cargo.lock that doesn't exist, so its key never changed; it's now keyed on the vcpkg manifest and registry baseline.
  • Permissions: every workflow sets its token permissions explicitly, so the repo default can be read-only.
    • release: contents: write.
    • CodeQL: security-events: write.
    • Labeler: pull-requests: write.
    • Setup job: pull-requests: read, for which-branch.
    • Everything else: contents: read or nothing.
    • The build job no longer asks for packages: write.
  • Hardening:
    • Workflow inputs and ref names reach scripts through environment variables instead of being pasted into them (inputs.project, inputs.channel, github.ref_name, the release URL, and the tag-release inputs).
    • Checkouts no longer leave the token in .git/config.
    • Fixes code scanning alert [Bug]: Online People on German language #37.
  • Build:
    • A new push to a PR cancels its older run.
    • fail-fast: false, so one platform failing doesn't cancel the others.
    • PRs that only touch docs, or GitHub files the build doesn't read, skip the build. Develop requires no status checks, so a skipped build can't block a merge.
    • The release body carries the tag's relnotes. They were extracted but never used.
    • The packaging job checks out only dotnet-tools.json instead of every submodule.
    • .tar.xz/.dmg artifacts upload without being compressed a second time.
    • Removed four dead matrix excludes and an unused step output.
  • Dependabot: now checks the composite action. It no longer proposes vcpkg baselines, because it bumps builtin-baseline without the submodule and every such PR failed to configure (Bump github.com/microsoft/vcpkg from master to 2026.07.29 in /indra #358).
  • Lint workflows: actionlint runs on .github changes, with shellcheck at warning level.
  • Labeler: dropped llcrashlogger and llmeshoptimizer, which no longer exist. Added alscript, llwebrtc, llphysicsextensionsos, media_plugins, and github_actions for .github/**.

Related Issues

  • Please link to a relevant GitHub issue for additional context.

Issue Link: none


Checklist

  • I have provided a clear title and detailed description for this pull request.
  • If useful, I have included media such as screenshots and video to show off my changes.
  • I have tested the changes locally and verified they work as intended. (actionlint passes with shellcheck at warning level, and zizmor reports only tag-pinned actions; nothing has run on GitHub before this PR)
  • All new and existing tests pass.
  • Code follows the project's style guidelines.
  • Documentation has been updated if needed.
  • Any dependent changes have been merged and published in downstream modules
  • I have reviewed the contributing guidelines.

Additional Notes

Repository settings this needs:

  1. Turn CodeQL default setup off (Settings → Code security → CodeQL analysis → switch to advanced). While it is on, GitHub rejects this workflow's uploads, so CodeQL fails on this PR until then.
  2. Create the labels alscript, llphysicsextensionsos, llwebrtc and media_plugins. The labeler can only create a label with issues: write, which it isn't given.
  3. Set the default workflow token to read (Settings → Actions → General → Workflow permissions), and stop Actions from approving pull requests. No workflow needs either.
  4. Close Bump github.com/microsoft/vcpkg from master to 2026.07.29 in /indra #358.

Expect long CodeQL C/C++ runs. A full Linux viewer build takes about 95 minutes, and tracing slows it further, so expect about 3–4.5 hours per platform. The job timeout is the 6-hour maximum.

Still open:

  • Writer keys reachable by anyone with write access. Anyone who can push a branch can still reach the R2 writer keys, by editing the workflow in their PR. Closing that needs the writer keys moved into an environment restricted to protected branches. That only helps once merges need review: the Release Branches ruleset requires 0 approvals, and its code-owner rule has no CODEOWNERS file to enforce.
  • Actions pinned by tag, not commit hash. Dependabot can maintain hash pins if wanted.

🤖 Generated with Claude Code

RyeMutt and others added 3 commits October 3, 2026 20:53
The configure step passed AL_GRID with quotes of its own, a leftover of
when the grid was a C string define. Since the install rules became the
package manifest, AL_GRID is a plain string checked against agni: the
quoted name never matched, so every CI build shipped a
settings_install.xml with CmdLineGridChoice set to "agni". The viewer
took that for a grid given on the command line, could not find it, and
in doing so skipped the user's last grid (CurrentGrid) and, at the login
panel, their saved start location.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Same-repository pull requests were given the writer keys and readwrite
mode as a temporary test to populate the cache. That let code still
under review put packages in the cache that release builds then use.
They are back on the read-only keys in read mode, as the cache was set
up; the read-only keys pass the cache's preflight, as the pull request
builds of 2026-09-20 showed. Only trusted builds of protected refs write.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… privilege

CodeQL's default setup read the C/C++ without building it: no vcpkg
header resolved, no platform #if decided, two and three quarter hours a
run. The CodeQL workflow traces a real build instead, on Linux and on
Windows, with the security-extended queries, plus Python and the
workflows themselves without a build. The configure runs before tracing
starts, so the vcpkg ports stay out of the database, and the build tree
sits outside the checkout, so their headers stay out of the alerts.
Linux keeps default setup's category, so its alerts and dismissals carry
over. Default setup has to be switched off for it to upload.

- A composite action, setup-build, holds the host packages, Python
  tools, vcpkg bootstrap and R2 cache setup the build and CodeQL share.
  Its Rust cache is keyed on the vcpkg manifest and registry baseline;
  the Cargo.lock it was keyed on never existed, so the key never moved.
- Every workflow names its token's permissions, so the repository's
  default can be read only: the release job writes contents, CodeQL
  writes security events, the labeler writes pull requests, the rest
  read or nothing. The build job no longer asks for packages: write.
- Inputs and ref names reach scripts through the environment, never
  pasted into them; checkouts keep no credentials.
- Build: a pull request's new push cancels its old run; one platform
  failing no longer cancels the others; pull requests that change only
  documentation or GitHub files no build reads do not build; the
  release carries the tag's relnotes; the packaging job checks out only
  dotnet-tools.json; the .tar.xz and .dmg packages upload without
  being compressed a second time; dead matrix excludes and step
  outputs are gone.
- Dependabot watches the composite action and no longer proposes vcpkg
  baselines: it moves builtin-baseline without the submodule, and every
  such pull request failed to configure.
- Lint workflows runs actionlint on changes under .github.
- The labeler drops libraries that are gone and labels alscript,
  llwebrtc, llphysicsextensionsos, media_plugins and .github.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ceae8dcc-3129-416c-993c-59411f4848b3
📥 Commits

Reviewing files that changed from the base of the PR and between d442ddf and a853d33.

📒 Files selected for processing (11)
  • .github/actionlint.yaml
  • .github/actions/setup-build/action.yaml
  • .github/codeql/codeql-config.yaml
  • .github/dependabot.yaml
  • .github/labeler.yaml
  • .github/workflows/build.yaml
  • .github/workflows/check-pr.yaml
  • .github/workflows/codeql.yaml
  • .github/workflows/label.yaml
  • .github/workflows/lint-workflows.yaml
  • .github/workflows/tag-release.yaml

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Summary

Summary by CodeRabbit

  • Build & Release

    • Updated build and release workflows, including release tagging, artifact packaging, and release notes.
    • Added support for additional hosted runner platforms and configurable build caching.
  • Quality & Security

    • Added automated checks for workflow configuration and expanded CodeQL analysis across supported code areas.
    • Tightened workflow permissions and added limits for selected build and release jobs.
  • Maintenance

    • Updated pull-request labeling and automated dependency-update coverage.

Walkthrough

The pull request adds reusable GitHub Actions build setup, revises build and release workflows, introduces CodeQL analysis and workflow linting, and updates repository automation rules.

Changes

Build and Code Analysis

Layer / File(s) Summary
Reusable build setup
.github/actionlint.yaml, .github/actions/setup-build/action.yaml
Adds runner labels and a composite action that installs platform-specific dependencies, bootstraps vcpkg, caches Rust dependencies, and conditionally configures the R2 cache.
Build and release workflow
.github/workflows/build.yaml
Updates build triggers, cache access, channel selection, matrix behavior, packaging, and release output handling.
CodeQL analysis
.github/codeql/codeql-config.yaml, .github/workflows/codeql.yaml
Adds a CodeQL configuration and analysis for Actions, Python, and manually built C/C++ targets on Linux and Windows.

Repository Automation

Layer / File(s) Summary
Update and label rules
.github/dependabot.yaml, .github/labeler.yaml
Updates Dependabot directory coverage and path-based label rules.
Workflow checks and tag creation
.github/workflows/check-pr.yaml, .github/workflows/label.yaml, .github/workflows/lint-workflows.yaml, .github/workflows/tag-release.yaml
Changes workflow permissions and timeouts, adds actionlint checks, and passes tag inputs through environment variables.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant BuildWorkflow as build.yaml
  participant SetupAction as setup-build action
  participant Vcpkg as vcpkg bootstrap
  participant R2Config as R2 cache configuration script
  BuildWorkflow->>SetupAction: Pass R2 mode, endpoint, bucket, and credentials
  SetupAction->>Vcpkg: Run the platform bootstrap script
  opt R2 cache mode is nonempty
    SetupAction->>R2Config: Configure cache with action inputs
  end
Loading

Merge Risk: ⚪ Minimal · up to a853d

The workflow changes appear mergeable after normal checks; no actionable build or release failure was established.

Security Architecture Review

Security architecture risk: 🔵 Low · up to a853d

Normal pull-request builds lose shared-cache write access, while release authority remains separated from ordinary builds. No introduced security issue was established, but protection against malicious workflow edits and the actual cache credential permissions could not be verified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The sensitive cache boundary is the shared vcpkg package source used by trusted builds. If unreviewed code obtained effective writer credentials, poisoned matching cache packages could affect downstream builds. The PR removes ordinary PR writer access; the credentials' maximum bucket or account scope is not available.

Security Findings and Attack Paths

  • inferred — A same-repository contributor able to submit workflow changes could potentially request writer secrets or alter the release gate if repository policies permit it. Those secret references and release-write authority existed at base; this is an inherited policy-dependent path, not an established PR-introduced vulnerability.

Trust Boundaries and Controls

  • observed — Normal CodeQL cache use selects only named reader credentials. Normal build PRs select reader credentials, while release execution depends on an Alchemy-tag-derived output and grants contents-write only in the release job. Reader credential names and a successful list preflight do not prove provider-enforced write denial.
  • observed — The pull_request_target labeler retains only contents-read and pull-requests-write permissions and contains no checkout or execution of PR code. The description check reads the event payload with an empty permission set.

Resilience and Maintainability Implications

  • inferred — Centralizing setup reduces duplicated cache configuration, but the composite action is executable code from the checkout, not an independent enforcement boundary. Durable protection of writer authority therefore depends on controls outside PR-editable workflow and action logic.

Hardening Proposals

  • proposed — Verify that writer and tag-creation credentials are protected by repository or environment controls that unreviewed workflow edits cannot bypass. Independently verify that reader credentials cannot upload, overwrite, or delete cache objects and are restricted to the intended cache scope.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Issue #358 is closed and completed, so it provides historical context only. No active, directly linked issue supplies coding requirements for this pull request.
Out of Scope Changes check ✅ Passed The reviewed change summary describes CI, CodeQL, cache, permissions, and workflow updates that match the pull request’s stated intent. It identifies no unrelated change. Issue #358 adds no scope beca…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Title check ✅ Passed The title clearly identifies the central CodeQL and least-privilege workflow changes. It is concise and specific.
Description check ✅ Passed The description includes the required sections and gives detailed context on the changes, testing status, related issues, checklist, and repository settings. It clearly notes that GitHub Actions have …
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit checks the build with care
Then hops through caches in the air
New labels mark the paths it knows
CodeQL scans where the workflow goes
It thumps: “All set!” and nibbles greens

Comment @coderabbitai help to get the list of available commands.

Without them the tree does not build: llstring.h calls std::strlen with
no <cstring> of its own, which the precompiled header always supplied,
and the Linux analysis stopped at httpstats.cpp. Turning them off was a
precaution only; the extractor reads the forced-include header as text
whether or not the compiler has a precompiled copy of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RyeMutt
RyeMutt merged commit 9194a42 into develop Oct 4, 2026
24 of 25 checks passed
@RyeMutt
RyeMutt deleted the rye/gha-codeql branch October 4, 2026 03:55
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