Skip to content

test: force-validate CodeQL severity gate (DO NOT MERGE)#1

Closed
norandom wants to merge 8 commits into
mainfrom
throwaway/codeql-gate-force-test
Closed

test: force-validate CodeQL severity gate (DO NOT MERGE)#1
norandom wants to merge 8 commits into
mainfrom
throwaway/codeql-gate-force-test

Conversation

@norandom
Copy link
Copy Markdown
Owner

Purpose

Force-validate the CodeQL severity gate in .github/workflows/scan.yml (task 4.2 of the build-and-security-modernization spec). This PR adds an intentional os/exec command-injection sink behind a build tag so the default go build is unaffected.

Expected outcome

  • The CodeQL — Go job's Fail on Critical/High findings step should exit non-zero.
  • SARIF should still upload to Code Scanning with the go/command-injection rule firing.
  • The PR check should appear red.

Cleanup

This PR will be closed without merging once the failing run is captured as evidence.

🤖 Generated with Claude Code

norandom and others added 3 commits May 14, 2026 15:33
Adds an intentional os/exec command-injection sink behind a build tag
so the default `go build` is unaffected. CodeQL's go/command-injection
rule fires at security-severity >= 7.0, which the scan workflow's jq
post-process step turns into a non-zero exit.

This commit lives on a throwaway branch and the PR is closed without
merge once we capture the failing gate observation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous build tag excluded throwaway_critical.go from `go build ./...`,
which is exactly the command CodeQL Go autobuild runs — so CodeQL saw
no Go file at all. Drop the tag and reference the function from an
init guarded by a sentinel arg, so the binary's runtime behavior is
unchanged but CodeQL extracts and analyzes the code path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ern)

Previous attempt used os.Args[1] as the taint source. CodeQL Go's
default CommandInjection query treats command-line argv as low-confidence
and produced 0 results. r.URL.Query().Get(...) is the canonical
HTTP-derived untrusted source the rule was authored to catch.

Two sinks: exec.Command(user-controlled) and os.Open(user-controlled-path).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Comment thread throwaway_critical.go
// `r.URL.Query().Get` is the canonical CodeQL untrusted source.
user := r.URL.Query().Get("cmd")
// nosemgrep: dangerous-exec-command, go.lang.security.audit.dangerous-exec-command.dangerous-exec-command
if err := exec.Command("sh", "-c", user).Run(); err != nil {
Comment thread throwaway_critical.go
}
path := r.URL.Query().Get("file")
// nosemgrep: go.lang.security.audit.dangerous-system-call
f, err := os.Open(path)
norandom and others added 5 commits May 14, 2026 15:49
A small number of SARIF results emitted by github/codeql-action lack a
ruleIndex (e.g., notification entries). Indexing into the rules array
with a null subscript made jq exit 5 with "Cannot index array with
null", which masked the actual count behind a parse error.

Guard the lookup with a type check so the gate falls back to the
result's own properties (or the "0" default) when ruleIndex is missing.
Verified locally against a SARIF mixing well-formed and ruleIndex-less
results: count returns 2 (Critical + High), no jq error.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… SARIF shape)

CodeQL Action emits the local SARIF with tool.driver.rules empty —
rule definitions land in tool.extensions[].rules instead, and each
result.rule has {id, index, toolComponent: {index}} pointing into
those extension arrays. The previous gate only checked driver.rules
and so always saw "0" for security-severity, even though Code Scanning
showed Critical/High alerts for the same SARIF.

New jq builds a ruleId → security-severity map from the union of
driver.rules and every extension's rules, then resolves each result
by its ruleId (or .rule.id fallback). Verified locally against a
synthetic SARIF that mirrors the throwaway PR's two findings
(go/command-injection 9.8, go/path-injection 7.5) — count: 2.

Debug echoes removed; the gate is back to a single clean run/exit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@norandom
Copy link
Copy Markdown
Owner Author

Closing without merge — task 4.2 (force-validate CodeQL severity gate) of build-and-security-modernization spec captured the expected failure. Evidence: run 25864818797 — 'Critical/High Go findings: 2' and ::error::CodeQL Go found 2 Critical/High results. SARIF surfaces both alerts in Code Scanning (go/command-injection 9.8 critical + go/path-injection 7.5 high). Gate logic verified end-to-end.

@norandom norandom closed this May 14, 2026
@norandom norandom deleted the throwaway/codeql-gate-force-test branch May 14, 2026 14:43
norandom added a commit that referenced this pull request May 14, 2026
…2 + 4.4

Force-validation: throwaway PR #1 (closed without merge) introduced an
intentional Critical Go finding. The codeql-go gate reported
'Critical/High Go findings: 2' and exited 1; both rules surfaced in
Code Scanning (go/command-injection 9.8, go/path-injection 7.5).

Release-trigger isolation: four push:main events between 12:35Z and
14:38Z all triggered scan.yml; none triggered go_build_release.yml.
Release workflow stays scoped to the v* tag pushes (v2.2.0, v2.3.0,
v2.3.1, v2.3.2) as required by R6.4.

Implementation Notes appended with the three findings worth carrying
forward: SARIF extensions-rules lookup, CodeQL Go HTTP-source
preference, and the packs:-as-string syntax.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

2 participants