From 78b6c012e6ccdc840c54ea92c062e153a6d70ae2 Mon Sep 17 00:00:00 2001 From: Toni Bergholm Date: Thu, 3 Sep 2026 11:25:35 +0300 Subject: [PATCH] ci(codeql): move config to a file and exclude rust/cleartext-logging Code scanning had 145 open high alerts, all from rust/cleartext-logging. The rule taints anything flowing out of a type or function whose name contains "Secret", then flags every println!/eprintln! downstream. In this codebase that is the entire secrets API by design, so every alert was on metadata that is public by construction: file paths ("skipped (no key): {path}"), secret names from the public registry, snapshot ids, and TLS fingerprints. None printed plaintext. Secret plaintext has one sanctioned egress, the child-process env injected by `sc run` (ADR-0008). There is no `sc secret show`; `sc secret list` emits names plus a recipient count. The one intentional plaintext print is `sc serve token add`, which prints a freshly minted token once and stores only its hash (ADR-0040). Exclude the rule via query-filters, and move the exclusions out of the inline `config:` block into .github/codeql/codeql-config.yml so each one carries its reason in a reviewable place. The exclusion's cost is recorded there too: it would hide a genuine cleartext egress, so the compensating controls are docs/THREAT-MODEL.md and the P5 commit-time secret scanner. The remaining critical alert (a deliberately-wrong key in a #[cfg(test)] negative test in crates/crypto/src/envelope.rs) is dismissed as a false positive rather than filtered: tests are inline per CLAUDE.md, so a paths-ignore entry would also blind rust/hard-coded-cryptographic-value to the real crypto in the same file. Co-Authored-By: Claude Opus 5 (1M context) --- .github/codeql/codeql-config.yml | 32 ++++++++++++++++++++++++++++++++ .github/workflows/codeql.yml | 9 +++------ 2 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 .github/codeql/codeql-config.yml diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 0000000..a1a1261 --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,32 @@ +# Shared CodeQL configuration for every language in .github/workflows/codeql.yml. +# Scope suppressions as narrowly as the mechanism allows: prefer a rule-level +# exclusion with a recorded reason over widening paths-ignore. + +name: src-control CodeQL config + +paths-ignore: + # The vendored glib source is third-party code, byte-identical to the + # published crate except for the documented soundness backport and lint cap. + # Its upstream FFI triggers false-positive pointer alerts. + - vendor/glib-0.18.5-patched/** + +query-filters: + # rust/cleartext-logging taints anything flowing out of a type or function + # whose name contains "Secret", then flags every println!/eprintln! + # downstream. In this codebase that is the entire secrets API by design, so + # the rule fires on metadata that is public by construction: file paths + # ("skipped (no key): {path}"), secret *names* from the public registry, + # snapshot ids, and TLS fingerprints. It produced 145 alerts, none of which + # printed plaintext. + # + # Secret plaintext has exactly one sanctioned egress — the child-process env + # injected by `sc run` (ADR-0008). There is no `sc secret show`; `sc secret + # list` emits names plus a recipient count. The one intentional plaintext + # print is `sc serve token add`, which prints a freshly minted token once and + # stores only its hash (ADR-0040). None of that is what this rule is for. + # + # If a real cleartext-logging egress is ever added, this exclusion hides it — + # so the compensating control is docs/THREAT-MODEL.md plus the commit-time + # secret scanner (P5), not this query. + - exclude: + id: rust/cleartext-logging diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b8b5fb2..53e680d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -37,12 +37,9 @@ jobs: with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - # The vendored glib source is third-party code, byte-identical to the - # published crate except for the documented soundness backport and - # lint cap. Its upstream FFI triggers false-positive pointer alerts. - config: | - paths-ignore: - - vendor/glib-0.18.5-patched/** + # Path and rule exclusions, each with its reason, live in the config + # file so they are reviewable in one place. + config-file: ./.github/codeql/codeql-config.yml - uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 with: category: "/language:${{ matrix.language }}"