Repository navigation
CodeQL dispatch cannot prove GHAS identity because target-repo analyses API returns 403 #2276
Description
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:
.github35276762974 - 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
- Determine which credential is intended to own cross-repository
code-scanning/analysesreads forcodeql-scan-dispatch.yml. - 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.
- Preserve fail-closed behavior for 401/403/transport errors; do not translate unreadable evidence into an empty identity set.
- 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(). - 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
seonghobae commentedon Sep 18, 2026
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/analysesread capability and fail closed when none does; it cannot itself create the missing target-repository permission. ForContextualWisdomLab/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.seonghobae commentedon Sep 22, 2026
2026-09-22 fresh downstream canary:
ContextualWisdomLab/LineageWeave#899@c943060c7c16f74faf48d1ee40eaa5301c830065reproduces this exact GHAS analysis-read failure after a clean Actions CodeQL scan.Canonical producer:
.githubrun35652904176, Actions job106584641235.83eba56149eb802cd63642c507c324c9976ec78ec943060c7c16f74faf48d1ee40eaa5301c830065files=1 results=0 medium_plus=0codeql-dispatch-actions-35652904176-1, artifact id10678416063, SHA-256f0bb821231120dc1be457362b862690effdf6c0e7ef207f10fd8496680097a28Verify GHAS base/head CodeQL configuration identityGET /repos/ContextualWisdomLab/LineageWeave/code-scanning/analysesreturns HTTP 403Resource not accessible by integrationThis 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.
seonghobae commentedon Sep 23, 2026
Fresh canonical reproduction from
.github#2352confirms this permission-path finding on the current central lifecycle, not only the older TEPP specimen.Exact producer run
35841640640is bound to.github#2352@f1a8dc813e6dba4e4905bf3e1b770b6d44344944, protected basee6334e229581a918e2f22de18733b76fa65d7e71, required CodeQL run35805450471.validate-dispatch107117846461: SUCCESS.107179921158: CodeQL analysis SUCCESS, Medium+ SARIF gate SUCCESS (files=1 results=0 medium_plus=0per the chore(foundation): converge AnyIO and CodeQL endpoint repairs #2352 receipt), then FAILURE only atVerify GHAS base/head CodeQL configuration identitybecause the analyses REST read returns HTTP 403Resource not accessible by integration.107179921308: same boundary — analysis/SARIF gate pass, GHAS configuration identity fails.github-tokenfallback can publish that status. That fallback does not solve GHAS analyses-read authority.107247432911is 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.
seonghobae commentedon Sep 23, 2026
Fresh #2352 producer state narrows this issue further. Run
35841640640has now completed its settlement job107247432911with SUCCESS. Python107179921158and Actions107179921308still completed FAILURE only atVerify 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 repositorycode-scanning/analysesread authority / credential canary owned here and by #2275. Preserve fail-closed identity verification; no BandScope-side workaround or broad rerun is indicated.seonghobae commentedon Sep 23, 2026
2026-09-24 KST independent ConceptWeave canary now reaches this same GHAS identity boundary.
Central dispatch
35870670165is bound toContextualWisdomLab/ConceptWeave#35@d7b7e30b278ec2f27096b4d313c7d5eaf5387ddc, protected basef4f440dd58c77d7cd90dff8a1eb2eeb9a9940425, required run35825042996, protected.github@e6334e229581a918e2f22de18733b76fa65d7e71.Actions job
107322443261obtained a runner and passed live PR revalidation, exact-head materialization, CodeQL initialization/analysis, and the Medium+ SARIF gate. It then failed exactly atVerify 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 exactcode-scanning/analysesendpoint. 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
107322443235remains runnerless queued and stays separately #712-owned. No manual/no-op wake or leaf-source movement.seonghobae commentedon Sep 23, 2026
Follow-up: Python has now reproduced the same identity-step failure as Actions on the ConceptWeave #35 canary.
Downstream
35870670165now has both107322443235(python) and107322443261(actions) terminal FAILURE only atVerify 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 job107396154783is 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.
seonghobae commentedon Sep 24, 2026
Additional real-target specimen from ConceptWeave #35, current as of 2026-09-24 KST:
Downstream handler
.githubrun35870670165is now fully terminal.validate-dispatch107213600319succeeded. Both target-language shards — Python107322443235and Actions107322443261— completed exact-head materialization, CodeQL initialization/analysis and the Medium+ SARIF gate, then failed only atVerify 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 runjob107396154783also acquired a runner and completed FAILURE atSettle 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.seonghobae commentedon Sep 24, 2026
OriginWeave consumer handoff (2026-09-24 KST):
ContextualWisdomLab/OriginWeave#37@219b43bfa87ab4fd90a77bb962df2797925bf661is another unchanged downstream canary for the same post-scan GHAS-identity boundary.Canonical producer
.githubrun35870614075validated the exact target PR/head/base tuple (validate-dispatch107213403257: SUCCESS). Actions107322434021, JavaScript/TypeScript107322434023, and Python107322434093each materialized the exact OriginWeave tree, initialized and ran CodeQL, and passed the Medium+ SARIF gate. All three then failed atVerify GHAS base/head CodeQL configuration identity. Follow-on settlement107392374879acquired the app token and failed atSettle 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 integrationevidence 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.seonghobae commentedon Sep 24, 2026
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 #22750d68d7a8435652edc288d7bb3dfb06a7c8a59eb6still has rollup FAILURE (its Python CodeQL compatibility job andcodeql-dispatch/actions/pythoncontexts); Draft #2352f1a8dc813e6dba4e4905bf3e1b770b6d44344944still 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 personalghtoken probe would test a different principal and must not be accepted as this canary. GitHub documentsCode scanning alertsrepository read permission on the target installation forGET /repos/{owner}/{repo}/code-scanning/analyses(classic PAT alternative:security_eventsscope): 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 runwait_for_language_pairing()and observe terminal exact-head statuses. Record 403, 5xx, and transport failures separately and fail closed; HTTP 200 with[]is insufficient becausepairing_ready()intentionally succeeds when no base language identity exists. No current-head rerun/cancel, protection bypass, or merge while this proof is missing.seonghobae commentedon Sep 25, 2026
Permission-owner handoff (2026-09-25 17:32 UTC; read-only installation inspection, no token disclosed):
0d68d7a8435652edc288d7bb3dfb06a7c8a59eb6/ base8da5f48fa0438ff33c766f03325f6e7f2a77dd9d. Use that route; do not open a duplicate PR.opencode-agentwithrepository_selection=all,permissions.security_events=nullandpermissions.statuses=read. The currentcodeql-scan-dispatch.ymlobtains that App token through trusted Actions OIDC. The original fix(strix): resolve evidence binder from trusted source #2291 actions job108038090597observedGET code-scanning/analysesHTTP 403 (Resource not accessible by integration), and status publication also observed HTTP 403. The installation permissions explain both failures.cwl-noema-reviewhassecurity_events=readbutstatuses=read; it is not the selected CodeQL token and cannot prove status publication.Code scanning alertsrepository read forGET /repos/{owner}/{repo}/code-scanning/analyses, andCommit statusesrepository write forPOST /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.githubandfast-mlsirmand wire it to fix(codeql): prove target GHAS analysis-read credential #2275 before execution. No permission or installation setting was changed here.ghcredential. Bind exact targets:.githubfix(strix): resolve evidence binder from trusted source #2291 basee6334e229581a918e2f22de18733b76fa65d7e71, head1794626af3473ef23b9c2e678c3f06fd6c11636f;fast-mlsirmcoverage-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 base00f5cb91b417e40102036eb31ab8a4b843c76076, heade1fa5189d21a6321b60e6b2ce3b9eb73d1a1625f. For each target and eachactions/pythonlanguage, require authenticated HTTP 200 and nonempty protected-base and exact-head CodeQL analyses with matchingcommit_sha,category, andanalysis_key; then requirewait_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.Commit statuses: writeon the same target repo, allow the trusted handler to publish its real terminalcodeql-dispatch/actionsandcodeql-dispatch/pythoncontexts 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.seonghobae commentedon Oct 4, 2026
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.