mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 14:51:30 +00:00
482e952dde
Two CodeQL runs (commits1122f5a+c4157fd) 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.
101 lines
4.3 KiB
YAML
101 lines
4.3 KiB
YAML
name: CodeQL
|
|
|
|
# Public-facing SAST baseline that complements the existing security-deep-scan
|
|
# workflow (gosec, osv-scanner, trivy, ZAP, semgrep, schemathesis, nuclei,
|
|
# testssl) with cross-file Go and JavaScript dataflow analysis. Results land
|
|
# in the repository's Security → Code scanning tab as a public signal — any
|
|
# operator/security team auditing certctl can see the scan history and
|
|
# triage state without asking.
|
|
#
|
|
# Why CodeQL in addition to gosec:
|
|
# - gosec is single-file pattern matching (catches obvious issues like
|
|
# `os/exec.Command(userInput)`); CodeQL does interprocedural taint
|
|
# tracking (catches the same issue when the userInput is laundered
|
|
# through several function calls or struct fields).
|
|
# - GitHub-native; no third-party SaaS license gate (works for BSL 1.1
|
|
# and other source-available licenses, unlike Aikido / Snyk / SonarCloud
|
|
# free tiers which require OSI-approved licenses).
|
|
# - SARIF results auto-deduplicate and persist on PRs, so reviewers see
|
|
# "this PR introduces N new findings" rather than re-running ad hoc.
|
|
#
|
|
# Findings that are intentional (e.g., the SSH connector's
|
|
# InsecureIgnoreHostKey, ACME DNS solver's intentional shell-out to operator-
|
|
# supplied scripts) get suppressed via inline `// codeql[<rule-id>]`
|
|
# comments OR via a `.github/codeql/codeql-config.yml` query-pack tweak —
|
|
# document the rationale in the same commit that adds the suppression so
|
|
# the public scan-tab readers see the threat-model justification.
|
|
|
|
on:
|
|
push:
|
|
branches: [master]
|
|
pull_request:
|
|
branches: [master]
|
|
schedule:
|
|
# Weekly Sunday 06:00 UTC, in addition to push/PR coverage. Catches
|
|
# rule-pack updates from CodeQL upstream (their Go/JS rulesets ship
|
|
# new queries on a roughly-monthly cadence).
|
|
- cron: '0 6 * * 0'
|
|
|
|
permissions:
|
|
contents: read
|
|
security-events: write # SARIF upload to GitHub code scanning
|
|
actions: read
|
|
|
|
jobs:
|
|
analyze:
|
|
name: Analyze (${{ matrix.language }})
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
language: [go, javascript-typescript]
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Go
|
|
if: matrix.language == 'go'
|
|
uses: actions/setup-go@v5
|
|
with:
|
|
# Match ci.yml + release.yml + security-deep-scan.yml.
|
|
go-version: '1.25.9'
|
|
|
|
- name: Initialize CodeQL
|
|
uses: github/codeql-action/init@v3
|
|
with:
|
|
languages: ${{ matrix.language }}
|
|
# Use the security-and-quality query suite — security finds plus
|
|
# maintainability/correctness issues that the smaller security-extended
|
|
# suite skips. Comparable scope to what Aikido / SonarCloud run.
|
|
queries: security-and-quality
|
|
# 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
|
|
# 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
|
|
|
|
- name: Perform CodeQL Analysis
|
|
uses: github/codeql-action/analyze@v3
|
|
with:
|
|
category: "/language:${{ matrix.language }}"
|
|
# SARIF upload is implicit (and is what populates the Security tab).
|