Skip to content

fix: address CodeQL security scan findings#177

Merged
mwiebe merged 1 commit into
OpenJobDescription:mainfrom
mwiebe:hardening6
May 11, 2026
Merged

fix: address CodeQL security scan findings#177
mwiebe merged 1 commit into
OpenJobDescription:mainfrom
mwiebe:hardening6

Conversation

@mwiebe
Copy link
Copy Markdown
Contributor

@mwiebe mwiebe commented May 11, 2026

What was the problem/requirement? (What/Why)

CodeQL findings to triage/address.

What was the solution? (How)

Improvements from CodeQL findings.

Pointer-safety (CodeQL tracker does not model Win32 out-parameter APIs):

  • crates/openjd-sessions/tests/integration/test_windows_permissions.rs: Add explicit !dacl_ptr.is_null() and !ace_ptr.is_null() asserts before the respective unsafe dereferences in get_aces_for_object. Both pointers are written by Win32 out-parameter APIs (GetNamedSecurityInfoW, GetAce), so the original code was correct; the asserts are defense-in-depth that also break the scanner's taint path.

  • crates/openjd-sessions/src/win32.rs: Add a null guard in environment_for_user after CreateEnvironmentBlock(...)? (returning an empty map), and add an early null-return in parse_environment_block. Documented the null-safety of the latter in its doc comment.

Cleartext-logging (POSIX UIDs and OpenJD session IDs are not credentials):

  • crates/openjd-sessions/tests/integration/test_cross_user.rs: Add a doc comment on test_cross_user_runner_uid explaining that POSIX UIDs are public on any POSIX system, this test runs only inside an isolated Docker container under the Cross-User (Linux) CI job, and that including UIDs in the assertion message is essential for diagnosing test failures.

  • crates/openjd-sessions/src/session.rs: Add a module-level "Session identifiers" doc section explaining that session_id is an opaque caller-supplied correlation key — not a bearer token, cookie, or credential — and is deliberately logged so operators can trace log output across a session. Add brief comments at the two call sites CodeQL flagged (log::info! during session init, and log::warn! in Drop for Session) cross-referencing the module-level rationale.

Workflow permissions (hardening):

  • .github/workflows/record_pr.yml: Add workflow-root permissions: {}. Caller forwards to a reusable workflow that declares its own contents: read; caller itself needs no token permissions.

  • .github/workflows/codeql.yml: Add workflow-root permissions: {}. Also add contents: read alongside the existing security-events: write in the forwarded job permissions (explicit rather than relying on the public-repo default grant for actions/checkout).

  • .github/workflows/responded.yml: Add workflow-root permissions: {}. Also fix the reusable workflow reference — reusable_responded.yml does not exist in OpenJobDescription/.github; the actual file is responded.yml. This workflow has been silently 404'ing on every issue_comment event since whenever the upstream rename happened.

  • .github/workflows/stale_prs_and_issues.yml: Add workflow-root permissions: {}. Job-level permissions (already correct and matching the reusable workflow's workflow_call declaration) preserved.

CI consolidation:

  • .github/workflows/openjd-for-js.yml: Removed. Merged into ci.yml as a new openjd-for-js job with its own wasm-specific cache. The original workflow triggered on push: mainline, which never matches anything in this repo (the active branch is main), so it was effectively running only on PRs. Consolidation fixes the trigger, satisfies the workflow-permissions hardening rule, and reduces workflow-file count.

  • .github/workflows/ci.yml: Add openjd-for-js job (build wasm32, run vitest). Separate cache key keeps it from interleaving with the native build-test cache.

  • AGENTS.md: Update the CI Pipeline table to list the new openjd-for-js job and point the wasm-bindgen-cli pin reference at its new location in ci.yml.

Verification:

  • cargo clippy --all-features --all-targets --workspace -- -D warnings
  • cargo test --workspace --exclude openjd-for-js
  • bash scripts/check_copyright_headers.sh
  • python3 YAML lint on all modified workflow files

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Improvements from CodeQL findings.

Pointer-safety (CodeQL tracker does not model Win32 out-parameter APIs):

- crates/openjd-sessions/tests/integration/test_windows_permissions.rs:
  Add explicit `!dacl_ptr.is_null()` and `!ace_ptr.is_null()` asserts
  before the respective unsafe dereferences in `get_aces_for_object`.
  Both pointers are written by Win32 out-parameter APIs
  (`GetNamedSecurityInfoW`, `GetAce`), so the original code was correct;
  the asserts are defense-in-depth that also break the scanner's taint
  path.

- crates/openjd-sessions/src/win32.rs: Add a null guard in
  `environment_for_user` after `CreateEnvironmentBlock(...)?` (returning
  an empty map), and add an early null-return in
  `parse_environment_block`. Documented the null-safety of the latter in
  its doc comment.

Cleartext-logging (POSIX UIDs and OpenJD session IDs are not credentials):

- crates/openjd-sessions/tests/integration/test_cross_user.rs: Add a doc
  comment on `test_cross_user_runner_uid` explaining that POSIX UIDs are
  public on any POSIX system, this test runs only inside an isolated
  Docker container under the Cross-User (Linux) CI job, and that
  including UIDs in the assertion message is essential for diagnosing
  test failures.

- crates/openjd-sessions/src/session.rs: Add a module-level "Session
  identifiers" doc section explaining that `session_id` is an opaque
  caller-supplied correlation key — not a bearer token, cookie, or
  credential — and is deliberately logged so operators can trace log
  output across a session. Add brief comments at the two call sites
  CodeQL flagged (`log::info!` during session init, and `log::warn!` in
  `Drop for Session`) cross-referencing the module-level rationale.

Workflow permissions (hardening):

- .github/workflows/record_pr.yml: Add workflow-root `permissions: {}`.
  Caller forwards to a reusable workflow that declares its own
  `contents: read`; caller itself needs no token permissions.

- .github/workflows/codeql.yml: Add workflow-root `permissions: {}`.
  Also add `contents: read` alongside the existing `security-events:
  write` in the forwarded job permissions (explicit rather than relying
  on the public-repo default grant for `actions/checkout`).

- .github/workflows/responded.yml: Add workflow-root `permissions: {}`.
  Also fix the reusable workflow reference — `reusable_responded.yml`
  does not exist in OpenJobDescription/.github; the actual file is
  `responded.yml`. This workflow has been silently 404'ing on every
  `issue_comment` event since whenever the upstream rename happened.

- .github/workflows/stale_prs_and_issues.yml: Add workflow-root
  `permissions: {}`. Job-level permissions (already correct and matching
  the reusable workflow's `workflow_call` declaration) preserved.

CI consolidation:

- .github/workflows/openjd-for-js.yml: Removed. Merged into ci.yml as a
  new `openjd-for-js` job with its own wasm-specific cache. The original
  workflow triggered on `push: mainline`, which never matches anything
  in this repo (the active branch is `main`), so it was effectively
  running only on PRs. Consolidation fixes the trigger, satisfies the
  workflow-permissions hardening rule, and reduces workflow-file count.

- .github/workflows/ci.yml: Add `openjd-for-js` job (build wasm32, run
  vitest). Separate cache key keeps it from interleaving with the native
  `build-test` cache.

- AGENTS.md: Update the CI Pipeline table to list the new
  `openjd-for-js` job and point the `wasm-bindgen-cli` pin reference at
  its new location in ci.yml.

Verification:
- cargo clippy --all-features --all-targets --workspace -- -D warnings
- cargo test --workspace --exclude openjd-for-js
- bash scripts/check_copyright_headers.sh
- python3 YAML lint on all modified workflow files

Signed-off-by: Mark <399551+mwiebe@users.noreply.github.com>
@mwiebe mwiebe requested a review from a team as a code owner May 11, 2026 23:40
@mwiebe mwiebe enabled auto-merge (rebase) May 11, 2026 23:40
@mwiebe mwiebe merged commit 8a48851 into OpenJobDescription:main May 11, 2026
19 checks passed
@mwiebe mwiebe deleted the hardening6 branch May 11, 2026 23:58
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