Skip to content

codeql: repaired SARIF gate now blocks every PR on a false-positive URL-sanitization finding in a contract test #2208

Description

@seonghobae

Symptom

codeql-dispatch/python fails with "CodeQL dispatch scan found unsuppressed Medium+ findings" on .github PR #2191 (run 34858661909, job 104164445171):

CODEQL_SARIF files=1 results=1 medium_plus=1
CODEQL_FINDING rule=py/incomplete-url-substring-sanitization security-severity=7.8
  path=tests/test_organization_commercial_readiness_loop_receipt_contract.py line=43
  message=The string [results-receiver.actions.githubusercontent.com:443](1) may be at an arbitrary position in the sanitized URL.

The flagged line is a contract assertion over workflow source text, not URL handling:

assert "results-receiver.actions.githubusercontent.com:443" in source

source is the read-in text of a workflow file; the assertion pins one harden-runner egress allowlist entry. Nothing here sanitizes or validates a URL, so this is a false positive as a security finding while being a correct match for the query's syntactic heuristic.

Why it started now — and why it will affect every PR

This is a direct, expected consequence of the #2150 repair (merged as #2155, d1d70e334, 2026-09-14 01:03Z). Before it, gather_findings resolved rules only against tool.driver.rules; the Python CodeQL artifact carries 0 driver rules and 43 rules in the codeql/python-queries extension, so every result scored None and the gate reported medium_plus=0 — fail-open. The repaired gate resolves the referenced tool component, so it now sees security-severity=7.8 and blocks, exactly as that PR's description said it would.

The finding is in a file on main, unmodified by the PR that surfaced it, so every PR scanned from now on hits it. #2060 currently shows codeql-dispatch/python=pass, but that is stale evidence: it was scanned before the repair landed.

Scan configuration is not the cause and has not regressed: codeql-scan-dispatch.yml:412-422 passes only languages/build-mode to codeql-action/init and category/upload/output to analyze. There is no config file, no paths-ignore, and no query-suite override anywhere in the repository, so the default suite runs over the whole tree including tests/.

This is not bypass-eligible

Per the governance rule, the infrastructure exception covers CI/runner/workflow failures. This is a content finding produced by a correctly functioning gate. It must be resolved on its merits, not merged around — even though I assess the finding itself to be a false positive, that assessment should be reviewed rather than self-applied.

Remediation options

  1. Rewrite the assertion so it is not a substring test. Compare against parsed allowlist entries (membership in a sequence) instead of in source. Preserves the exact-string contract; removes the heuristic match. Narrowest change, no new mechanism.
  2. Scope the scan. Add a CodeQL config with paths-ignore for tests/, or a query-suite selection. Broadest effect, needs its own justification: it would stop scanning test code repository-wide.
  3. Suppress the single finding. The repository currently uses no # codeql[...]/# lgtm[...] suppression anywhere, so this would introduce a new convention; per the warning-handling rule a suppression needs an owner, a justification, and a review date, and is the least preferred of the three.

Option 1 looks right to me, but the file is tests/test_organization_commercial_readiness_loop_receipt_contract.py and I am not its writer, so I am not taking it.

Notes for whoever picks this up

  • Lines 44-45 use the same in source shape (*.actions.githubusercontent.com:443, *.blob.core.windows.net:443) and were not flagged — the leading *. stops the hostname heuristic. Only line 43 needs changing.
  • The same rule produced the two DOI-substring findings recorded on fast-mlsirm#1838, so this pattern recurs across the organization; a fix here does not generalize on its own.
  • Zero open PRs currently touch the flagged file, so the lane is free.

Filed from PR #2191, whose own diff is one unrelated test file.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions