ci(codeql): rewire local model pack discovery — fix d8026d5 silent no-op

Two CodeQL runs (commits d8026d5 + 4bb7a74) since the initial Option A
landing both completed with conclusion=success but failed to dismiss
alert #23 (go/request-forgery on scep_probe.go:232). Root cause: the
local pack never loaded.

The bug was in codeql-config.yml — `packs: { go: ['./'] }` looked
plausible (the path is relative to the config file's directory) but
the `packs:` field requires pack NAMES, not paths. Discovery of
unpublished local packs goes through the codeql-action `init` step's
`additional-packs:` input, not through `packs:`.

Verified pattern by reading github/vscode-codeql's working
.github/codeql/ setup. The supported chain:

   workflow init step      passes additional-packs: <parent-dir>
                                        ↓
       CodeQL CLI           registers each pack under the parent
                                        ↓
   codeql-config.yml        names the pack in `packs: go: [name]`
                                        ↓
       CodeQL CLI           resolves the name → pack on disk
                                        ↓
   pack's qlpack.yml        declares extensionTargets: codeql/go-all
                                        ↓
   data extension YAML      auto-loads, applies the barrier rows

Restructure to match this chain:

  Before                                    After
  --------                                  -----
  .github/codeql/qlpack.yml                .github/codeql/codeql-config.yml
  .github/codeql/models/                   .github/codeql/certctl-models/
    request-forgery-sanitizers.model.yml     qlpack.yml
  .github/codeql/codeql-config.yml           models/
                                               request-forgery-sanitizers.model.yml

The new `.github/codeql/certctl-models/` is the pack directory, named
to match `name: shankar0123/certctl-models` in qlpack.yml. Its parent
`.github/codeql/` is what additional-packs points at. The action
discovers the pack by walking the parent dir, sees the qlpack.yml,
registers the name, and `packs:` lookup succeeds.

Three concrete changes:

  - Pack moves from .github/codeql/{qlpack.yml, models/} into the
    sibling subdirectory .github/codeql/certctl-models/.

  - codeql-config.yml's packs: directive now uses the pack NAME
    (`shankar0123/certctl-models`) instead of the broken `./` path.

  - codeql.yml's Initialize CodeQL step gains
    `additional-packs: .github/codeql` so the CLI's resolver knows
    where to find unpublished packs.

Belt-and-suspenders correctness fix: the model row's `subtypes`
column now uses `False` (Python-style capitalized) instead of `false`
to match every shipped CodeQL Go .model.yml convention. SnakeYAML
accepts lowercase too — this is a hedge against any strict-format
tooling in the path.

Why this matters: alert #23 is rated Critical with CWE-918 + CWE-180.
The runtime defense is correct (validate-then-pin via
ValidateSafeURL + SafeHTTPDialContext), but the analyzer doesn't
know it. With the pack actually loading this time, the next CodeQL
run will see the barrier and dismiss the alert at source. Same fix
implicitly applies to the webhook notifier's outbound client.Do
(the second site that uses ValidateSafeURL).

Operator: push and watch the next CodeQL run dismiss alert #23. If
it doesn't, the next iteration will be on the YAML row's column
shape — most likely a one-line tweak, not another redesign.
This commit is contained in:
shankar0123
2026-05-01 01:08:48 +00:00
parent 4bb7a748ac
commit ccda277c18
4 changed files with 54 additions and 22 deletions
@@ -54,4 +54,8 @@ extensions:
pack: codeql/go-all
extensible: barrierModel
data:
- ["github.com/shankar0123/certctl/internal/validation", "", false, "ValidateSafeURL", "", "", "Argument[0]", "request-forgery", "manual"]
# subtypes uses Python-style `False` (capitalized) to match every
# shipped CodeQL Go .model.yml — see e.g. github/codeql/go/ql/lib/ext/
# database.sql.model.yml. SnakeYAML accepts lowercase too, but
# capitalized matches the canonical convention.
- ["github.com/shankar0123/certctl/internal/validation", "", False, "ValidateSafeURL", "", "", "Argument[0]", "request-forgery", "manual"]
@@ -21,10 +21,23 @@
# - Future code that flows operator URLs through ValidateSafeURL gets the
# same treatment automatically.
#
# Loading: codeql-config.yml's `packs:` field references this pack by its
# `name` below. The `extensionTargets:` map declares which upstream pack the
# extension data plugs into (codeql/go-all is the Go standard library pack).
# The `dataExtensions:` glob matches the .model.yml files in models/.
# Pack-loading mechanism (post-correction in commit fix-up):
# - This pack lives at .github/codeql/certctl-models/. Its NAME is the
# `name:` field below.
# - .github/workflows/codeql.yml's Initialize CodeQL step passes
# `additional-packs: .github/codeql` to the action — that's the parent
# directory the CodeQL CLI's resolver searches for unpublished packs.
# - .github/codeql/codeql-config.yml then references this pack by NAME
# in `packs: { go: [shankar0123/certctl-models] }`. The CLI looks the
# name up against the additional-packs path, finds this qlpack.yml,
# loads the pack and its data extensions.
#
# An earlier draft (commit d8026d5) tried `packs: { go: ['./'] }` in
# codeql-config.yml, which is the wrong syntax — that field expects pack
# names, not paths. The pack silently never loaded; alert #23 stayed open
# across two CodeQL runs (d8026d5 + 4bb7a74). Pack-name + additional-packs
# is the supported path; verified against the github/vscode-codeql working
# example.
#
# MaD `barrierModel` extension was added for Go in CodeQL 2.25.2 (2026-04-21).
# `github/codeql-action@v3` (pinned in .github/workflows/codeql.yml) pulls a
@@ -33,7 +46,7 @@
# regressed below 2.25.2 — pin a newer action version rather than reverting
# this pack.
name: shankar0123/certctl-codeql-models
name: shankar0123/certctl-models
version: 0.0.1
library: true
extensionTargets:
+14 -9
View File
@@ -7,9 +7,10 @@
# so that disabling the action's default suite via `disable-default-
# queries: true` doesn't accidentally drop coverage.
#
# 2. Load the local model pack at .github/codeql/, which adds project-
# specific Models-as-Data extensions (sanitizers, sinks, summaries)
# for the standard Go queries. See ./qlpack.yml for the full motivation.
# 2. Load the local model pack at .github/codeql/certctl-models/, which
# adds project-specific Models-as-Data extensions (barriers, sinks,
# summaries) for the standard Go queries. See
# certctl-models/qlpack.yml for the full motivation.
#
# Path-ignore is intentionally empty — every path that ships with the
# repo is in scope. Test files are NOT excluded; if a vulnerability
@@ -25,12 +26,16 @@ name: certctl-codeql
queries:
- uses: security-and-quality
# Load the local model pack. This is what makes the SSRF sanitizer
# barrier rows in models/request-forgery-sanitizers.model.yml apply to
# the standard go/request-forgery query.
# Load the local model pack BY NAME. The action's `init` step resolves
# this name against the path it was given via `additional-packs: .github/
# codeql` — that path is the parent directory of certctl-models/, where
# the pack's qlpack.yml declares `name: shankar0123/certctl-models`.
#
# `${{ }}` is not used here — the path is relative to the config file's
# directory, not to the repo root, per CodeQL action docs.
# An earlier draft used `packs: { go: ['./'] }` (a relative path). That's
# the wrong syntax — the `packs:` field expects pack NAMES, not paths.
# Local-by-path is not supported here; the discovery happens via
# additional-packs + name lookup. Verified against the github/vscode-codeql
# working setup.
packs:
go:
- ./
- shankar0123/certctl-models
+17 -7
View File
@@ -70,15 +70,25 @@ jobs:
# maintainability/correctness issues that the smaller security-extended
# suite skips. Comparable scope to what Aikido / SonarCloud run.
queries: security-and-quality
# Custom config + model pack at .github/codeql/. The pack declares
# Custom config that pulls in the local model pack at
# .github/codeql/certctl-models/. The pack declares
# internal/validation.ValidateSafeURL as a request-forgery barrier
# via Models-as-Data, dismissing the alert that fires at every site
# using the validator (scep_probe.go, webhook.go) without per-line
# `// codeql[...]` suppressions. See .github/codeql/qlpack.yml for
# the full motivation. Requires CodeQL CLI ≥ 2.25.2 for the
# barrierModel extension; codeql-action@v3 ships a recent enough
# CLI by default.
# via Models-as-Data, dismissing the alert that fires at every
# call site using the validator (scep_probe.go, webhook.go)
# without per-line `// codeql[...]` suppressions. See
# .github/codeql/certctl-models/qlpack.yml for the full motivation.
# Requires CodeQL CLI ≥ 2.25.2 for the barrierModel extension;
# codeql-action@v3 ships a recent enough CLI by default.
config-file: ./.github/codeql/codeql-config.yml
# Tells the CodeQL CLI's pack resolver where to find unpublished
# local packs. The pack referenced by name in codeql-config.yml's
# `packs:` directive (shankar0123/certctl-models) is resolved
# against this path. Without it, the name would fail to resolve
# and the pack would silently not load — that's exactly what
# happened to commits d8026d5 + 4bb7a74 (alert #23 stayed open
# across two CodeQL runs because the pack never made it into the
# analysis). Verified pattern: github/vscode-codeql.
additional-packs: .github/codeql
- name: Autobuild
uses: github/codeql-action/autobuild@v3