Skip to content

CodeQL dispatch cannot prove GHAS identity because target-repo analyses API returns 403 #2276

Open

Description

@seonghobae

Finding

The central CodeQL dispatch can complete an exact-head Python scan and produce clean SARIF, but its GHAS base/head configuration-identity proof cannot read the target repository's Code Scanning analyses.

Reproduced on ContextualWisdomLab/TEPP#538:

  • target head: 0a6947b11f2dba9e161f2abe8bdec0f652d4b47a
  • protected base: a243f18da4a4ca8a8d068c39922537f1f8ed6ad0
  • required target-repo CodeQL run: 35045658451
  • canonical owner dispatch run: .github 35276762974
  • canonical source: .github@64aa08d7fa487deacd41c761c36277ca68cab6c9
  • Python SARIF gate: files=1 results=0 medium_plus=0

Immediately afterward, Verify GHAS base/head CodeQL configuration identity called scripts/ci/codeql_ghas_configuration_identity.py, which requests GET /repos/ContextualWisdomLab/TEPP/code-scanning/analyses. The authenticated request failed:

GitHub API GET failed with HTTP 403: {"message":"Resource not accessible by integration", ...}

The same run later received HTTP 403 when attempting cross-repository commit-status publication with the available target App/GITHUB tokens. That status-publication gap is related to #1929, but this issue owns the distinct Code Scanning analyses read authority required by the newer GHAS identity contract.

Why this is not a TEPP source finding

The exact Python CodeQL analysis itself completed and its SARIF gate reported zero results. The failure occurs only when the central owner tries to query authenticated GHAS analysis metadata in the target repository. Treating 403 as “no baseline” would weaken the identity proof and is not acceptable.

Required repair

  1. Determine which credential is intended to own cross-repository code-scanning/analyses reads for codeql-scan-dispatch.yml.
  2. Give that credential the narrow target-repository permission needed to list Code Scanning analyses (GitHub App installation/repository security-events/code-scanning read as applicable), without broadening unrelated write authority.
  3. Preserve fail-closed behavior for 401/403/transport errors; do not translate unreadable evidence into an empty identity set.
  4. Add a contract/canary proving an unchanged target PR head can read both protected-base and exact-head CodeQL analyses and complete wait_for_language_pairing().
  5. Re-run the TEPP Give direct-OpenAI Strix scans GitHub Models fallbacks #538 exact-head dispatch after the current TEPP repair head is available; Python and Actions shards must both produce authenticated current-head verdicts.

Boundary

This is a canonical .github/GitHub App permission-path repair. Do not copy the identity logic into TEPP and do not weaken target-repository CodeQL gates. The separate TEPP Actions cache-poisoning findings are tracked in TEPP #594 and are being repaired in the TEPP owner.

Activity

  1. seonghobae commented on Sep 18, 2026

    @seonghobae
    ContributorAuthor

    Naruon consumer handoff (2026-09-19 KST): this issue is a distinct prerequisite from #2275, not a duplicate of it. #2275 can select the first configured credential that actually proves code-scanning/analyses read capability and fail closed when none does; it cannot itself create the missing target-repository permission. For ContextualWisdomLab/naruon, do not treat #2275 source/hosted acceptance alone as satisfying the central CodeQL boundary. The owner path must also prove this #2276 permission/canary contract on an unchanged real target: protected-base + exact-head analyses are readable, wait_for_language_pairing() completes, and unreadable 401/403 evidence remains fail-closed. Cross-repository commit-status publication remains separately owned by #1929. Naruon will not copy this credential/permission logic into a leaf workflow.

  2. seonghobae commented on Sep 22, 2026

    @seonghobae
    ContributorAuthor

    2026-09-22 fresh downstream canary: ContextualWisdomLab/LineageWeave#899@c943060c7c16f74faf48d1ee40eaa5301c830065 reproduces this exact GHAS analysis-read failure after a clean Actions CodeQL scan.

    Canonical producer: .github run 35652904176, Actions job 106584641235.

    • target protected base: 83eba56149eb802cd63642c507c324c9976ec78e
    • target exact head: c943060c7c16f74faf48d1ee40eaa5301c830065
    • CodeQL initialization/analysis: completed
    • Medium+ SARIF gate: files=1 results=0 medium_plus=0
    • retained artifact: codeql-dispatch-actions-35652904176-1, artifact id 10678416063, SHA-256 f0bb821231120dc1be457362b862690effdf6c0e7ef207f10fd8496680097a28
    • first failing post-scan boundary: Verify GHAS base/head CodeQL configuration identity
    • exact failure: target GET /repos/ContextualWisdomLab/LineageWeave/code-scanning/analyses returns HTTP 403 Resource not accessible by integration

    This is therefore another unchanged exact-head canary for #2276, not a LineageWeave Actions-source finding. Keep the current fail-closed behavior: clean SARIF does not substitute for authenticated base/head GHAS identity. Canonical source repair remains #2275; do not copy selector/credential logic into LineageWeave.

  3. seonghobae commented on Sep 23, 2026

    @seonghobae
    ContributorAuthor

    Fresh canonical reproduction from .github#2352 confirms this permission-path finding on the current central lifecycle, not only the older TEPP specimen.

    Exact producer run 35841640640 is bound to .github#2352@f1a8dc813e6dba4e4905bf3e1b770b6d44344944, protected base e6334e229581a918e2f22de18733b76fa65d7e71, required CodeQL run 35805450471.

    • validate-dispatch 107117846461: SUCCESS.
    • Python scan 107179921158: CodeQL analysis SUCCESS, Medium+ SARIF gate SUCCESS (files=1 results=0 medium_plus=0 per the chore(foundation): converge AnyIO and CodeQL endpoint repairs #2352 receipt), then FAILURE only at Verify GHAS base/head CodeQL configuration identity because the analyses REST read returns HTTP 403 Resource not accessible by integration.
    • Actions scan 107179921308: same boundary — analysis/SARIF gate pass, GHAS configuration identity fails.
    • Both jobs preserve SARIF and publish bounded dispatch status; the target app token cannot publish status either, while the same-repository github-token fallback can publish that status. That fallback does not solve GHAS analyses-read authority.
    • Settlement job 107247432911 is still queued.

    This is clean-SARIF + unreadable identity evidence, not a source finding. Preserve fail-closed behavior. The repair remains the narrow credential/API permission path owned here; do not treat 403 as empty analysis history or remove identity verification. #2275 remains the source selector lane, while this issue remains the real permission/canary owner.

  4. seonghobae commented on Sep 23, 2026

    @seonghobae
    ContributorAuthor

    Fresh #2352 producer state narrows this issue further. Run 35841640640 has now completed its settlement job 107247432911 with SUCCESS. Python 107179921158 and Actions 107179921308 still completed FAILURE only at Verify GHAS base/head CodeQL configuration identity; both had already completed CodeQL analysis and the Medium+ SARIF gate successfully. Thus pending settlement is no longer a blocker. The remaining causal boundary is the target repository code-scanning/analyses read authority / credential canary owned here and by #2275. Preserve fail-closed identity verification; no BandScope-side workaround or broad rerun is indicated.

  5. seonghobae commented on Sep 23, 2026

    @seonghobae
    ContributorAuthor

    2026-09-24 KST independent ConceptWeave canary now reaches this same GHAS identity boundary.

    Central dispatch 35870670165 is bound to ContextualWisdomLab/ConceptWeave#35@d7b7e30b278ec2f27096b4d313c7d5eaf5387ddc, protected base f4f440dd58c77d7cd90dff8a1eb2eeb9a9940425, required run 35825042996, protected .github@e6334e229581a918e2f22de18733b76fa65d7e71.

    Actions job 107322443261 obtained a runner and passed live PR revalidation, exact-head materialization, CodeQL initialization/analysis, and the Medium+ SARIF gate. It then failed exactly at Verify GHAS base/head CodeQL configuration identity; SARIF preservation and dispatch-status publication both completed afterward. This is not a ConceptWeave source finding and is no longer a runner-starvation classification for the actions shard.

    The job summary available through the Actions API identifies the failing step but not the step stderr, so I am not asserting this exact specimen's HTTP response. However, #2352's current central producer independently reaches the same step and records HTTP 403 Resource not accessible by integration, while #2275 owns credential selection for the exact code-scanning/analyses endpoint. Treat the ConceptWeave specimen as an additional unchanged-target reproduction requiring this owner path, not as authority to weaken the identity proof.

    The paired python shard 107322443235 remains runnerless queued and stays separately #712-owned. No manual/no-op wake or leaf-source movement.

  6. seonghobae commented on Sep 23, 2026

    @seonghobae
    ContributorAuthor

    Follow-up: Python has now reproduced the same identity-step failure as Actions on the ConceptWeave #35 canary.

    Downstream 35870670165 now has both 107322443235 (python) and 107322443261 (actions) terminal FAILURE only at Verify GHAS base/head CodeQL configuration identity; both passed exact-head materialization, CodeQL analysis and the Medium+ SARIF gate, then preserved evidence and published dispatch status. A new settlement job 107396154783 is queued.

    This turns the ConceptWeave specimen from one-language evidence into a complete two-language reproduction of this issue's boundary. The Actions API still exposes step conclusions rather than stderr, so #2352 remains the exact HTTP-403 specimen; do not infer or suppress the proof. Repair still belongs in #2275/#2276, with #1929 handling required-run lifecycle reconciliation.

  7. seonghobae commented on Sep 24, 2026

    @seonghobae
    ContributorAuthor

    Additional real-target specimen from ConceptWeave #35, current as of 2026-09-24 KST:

    Downstream handler .github run 35870670165 is now fully terminal. validate-dispatch 107213600319 succeeded. Both target-language shards — Python 107322443235 and Actions 107322443261 — completed exact-head materialization, CodeQL initialization/analysis and the Medium+ SARIF gate, then failed only at Verify GHAS base/head CodeQL configuration identity; SARIF preservation and dispatch-status publication succeeded afterward. The run has two nonexpired, nonempty SARIF artifacts (codeql-dispatch-python-35870670165-1, codeql-dispatch-actions-35870670165-1).

    The later settle exact required run job 107396154783 also acquired a runner and completed FAILURE at Settle exact CodeQL required run. I do not have step stderr that proves which individual settlement guard/token POST failed, so this is not being collapsed into the analyses-read 403 finding. It is separate central lifecycle/recovery evidence.

    The important owner conclusion remains unchanged: ConceptWeave #35 source is not the GHAS-identity defect. The two independent language shards reproduce the same fail-closed identity boundary on exact #35 head d7b7e30b278ec2f27096b4d313c7d5eaf5387ddc, strengthening #2275/#2276 as the credential/target-permission owner path. No leaf rerun or source movement should be used as a substitute for the permission canary required here.

  8. seonghobae commented on Sep 24, 2026

    @seonghobae
    ContributorAuthor

    OriginWeave consumer handoff (2026-09-24 KST): ContextualWisdomLab/OriginWeave#37@219b43bfa87ab4fd90a77bb962df2797925bf661 is another unchanged downstream canary for the same post-scan GHAS-identity boundary.

    Canonical producer .github run 35870614075 validated the exact target PR/head/base tuple (validate-dispatch 107213403257: SUCCESS). Actions 107322434021, JavaScript/TypeScript 107322434023, and Python 107322434093 each materialized the exact OriginWeave tree, initialized and ran CodeQL, and passed the Medium+ SARIF gate. All three then failed at Verify GHAS base/head CodeQL configuration identity. Follow-on settlement 107392374879 acquired the app token and failed at Settle exact CodeQL required run.

    This is not an OriginWeave source/SARIF finding and the leaf remains fail-closed. I do not have #37's identity-step stderr in the current evidence surface, so I am not claiming that this exact consumer independently proves HTTP 403; #2352/LineageWeave already provide that narrower Resource not accessible by integration evidence for this owner issue. Use #37 as an unchanged OriginWeave acceptance canary after #2275/#2276 repair: the exact base/head analysis identity must become readable and terminal current-head verdict publication must complete without copying credential logic into OriginWeave, synthesizing status, or blind-rerunning the leaf.

  9. self-assigned this
    on Sep 24, 2026
  10. seonghobae commented on Sep 24, 2026

    @seonghobae
    ContributorAuthor

    Owner/first-execution handoff at 2026-09-24 19:04 UTC: assigned this issue to the organization GitHub App permission operator seonghobae. Current GraphQL heads before judgment: canonical Draft #2275 0d68d7a8435652edc288d7bb3dfb06a7c8a59eb6 still has rollup FAILURE (its Python CodeQL compatibility job and codeql-dispatch/actions/python contexts); Draft #2352 f1a8dc813e6dba4e4905bf3e1b770b6d44344944 still has both dispatch contexts FAILURE. No merge or rerun is authorized by the local 3/3 selector tests. The first live selected-credential canary cannot be executed from this terminal: the installation token is minted inside the trusted Actions OIDC exchange and is not available here, while shared REST core returned HTTP 403 rate limit. A personal gh token probe would test a different principal and must not be accepted as this canary. GitHub documents Code scanning alerts repository read permission on the target installation for GET /repos/{owner}/{repo}/code-scanning/analyses (classic PAT alternative: security_events scope): https://docs.github.com/en/rest/code-scanning/code-scanning#list-code-scanning-analyses-for-a-repository . Operator decision: inspect the selected App installation and target repository access/Code Scanning enablement; grant only the missing analysis-read permission if required, without exposing a token or broadening unrelated write rights. First valid execution after the protected #2275 selector and permission path are available: use the actual selected credential in trusted context to query a target with a known protected-base CodeQL analysis, filter protected base and exact PR head, require nonempty CodeQL rows with matching base/head commit SHA, category, and analysis_key, then run wait_for_language_pairing() and observe terminal exact-head statuses. Record 403, 5xx, and transport failures separately and fail closed; HTTP 200 with [] is insufficient because pairing_ready() intentionally succeeds when no base language identity exists. No current-head rerun/cancel, protection bypass, or merge while this proof is missing.

  11. seonghobae commented on Sep 25, 2026

    @seonghobae
    ContributorAuthor

    Permission-owner handoff (2026-09-25 17:32 UTC; read-only installation inspection, no token disclosed):

    • Existing owner: @seonghobae; canonical Draft fix(codeql): prove target GHAS analysis-read credential #2275 remains OPEN at head 0d68d7a8435652edc288d7bb3dfb06a7c8a59eb6 / base 8da5f48fa0438ff33c766f03325f6e7f2a77dd9d. Use that route; do not open a duplicate PR.
    • The org installation API reports opencode-agent with repository_selection=all, permissions.security_events=null and permissions.statuses=read. The current codeql-scan-dispatch.yml obtains that App token through trusted Actions OIDC. The original fix(strix): resolve evidence binder from trusted source #2291 actions job 108038090597 observed GET code-scanning/analyses HTTP 403 (Resource not accessible by integration), and status publication also observed HTTP 403. The installation permissions explain both failures. cwl-noema-review has security_events=read but statuses=read; it is not the selected CodeQL token and cannot prove status publication.
    • GitHub's endpoint requirements are Code scanning alerts repository read for GET /repos/{owner}/{repo}/code-scanning/analyses, and Commit statuses repository write for POST /repos/{owner}/{repo}/statuses/{sha}. The App developer must request these two permissions for the opencode-agent App, and the ContextualWisdomLab installation owner must review/approve the changed installation. Since this installation currently selects all org repositories, the administrator must explicitly accept that scope or choose a separate, narrowly selected App installation for .github and fast-mlsirm and wire it to fix(codeql): prove target GHAS analysis-read credential #2275 before execution. No permission or installation setting was changed here.
    • First real canary must run with the token selected inside the trusted OIDC Actions handler, not this terminal's gh credential. Bind exact targets: .github fix(strix): resolve evidence binder from trusted source #2291 base e6334e229581a918e2f22de18733b76fa65d7e71, head 1794626af3473ef23b9c2e678c3f06fd6c11636f; fast-mlsirm coverage-evidence: trusted coverage image build fails at base VCS step — 'locked VCS source fast-mlsirm has a missing or ambiguous import root' blocks every contextual-orchestrator PR #2157 base 00f5cb91b417e40102036eb31ab8a4b843c76076, head e1fa5189d21a6321b60e6b2ce3b9eb73d1a1625f. For each target and each actions/python language, require authenticated HTTP 200 and nonempty protected-base and exact-head CodeQL analyses with matching commit_sha, category, and analysis_key; then require wait_for_language_pairing() to accept that pair. fix(codeql): prove target GHAS analysis-read credential #2275's current selector only probes HTTP 200 and therefore is not itself this proof; the identity helper can return ready when no base identity exists. Record 403, 5xx and transport errors separately and fail closed. Existing SARIF finding verdicts remain independent.
    • With an explicitly selected credential holding Commit statuses: write on the same target repo, allow the trusted handler to publish its real terminal codeql-dispatch/actions and codeql-dispatch/python contexts to that exact PR head. Verify the returned creator, context, SHA, target run and current-head check receipt. Do not synthesize a green status or manually rerun a blocked current-head workflow to manufacture a canary. If any permission/identity/status check fails, leave fix(codeql): prove target GHAS analysis-read credential #2275 Draft and the required gates blocked; revert the added App permission or restrict/revoke the selected installation if it exceeds the approved repo scope. No gate bypass, merge, or status relabeling.
  12. seonghobae commented on Oct 4, 2026

    @seonghobae
    ContributorAuthor

    BandScope downstream RCA, 2026-10-04 KST: #1176 target head 8fe6b6d99c009527ef0bcba419e6f6debdb23c23 has required wrapper run 34072437359. Actual central producers34080280416/34080311518/34080315145 at c9052e6 failed terminal commit-status POST with HTTP403 Resource not accessible by integration for both target-app-token and github-token. No currenthead receipt was posted. Please exercise the deployed selector with the actual trusted OIDC-selected credential, authenticated nonempty protected-base/head CodeQL identity rows and genuine exact-head terminal status plus exact required-job wake; not a personal gh token canary. Current central source37b10243 and merged coverage repair#2360 must be used instead of replaying obsolete PR chains. #1176 is now ready; a canonical unchangedhead review request is comment5978218837. This consumer will not duplicate credential logic, synthesize statuses, bypass checks, or claim old producer failures are source findings. Owner stays seonghobae. Narrow App permission/installation changes need explicit operator approval; none changed here.

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingpriority: highHigh-priority or P1 work

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions