From 0c265632aa7266e447ddb4aacfbd6f799b88b69a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 13 Jul 2026 14:04:18 +0900 Subject: [PATCH] fix(opencode): read same-repo code-scanning alerts with the runner token The model-unavailable evidence fallback reads open code-scanning alerts through CODE_SCANNING_GH_TOKEN, whose configured chain resolves to the OpenCode app token (no PAT secrets exist). The app installation has no security_events permission, so the read 403s and the fallback is skipped with 'open code-scanning alerts could not be read' on every eligible PR. The publish step's own runner token already carries this job's security-events: read grant, and for pull_request_target runs the lookup repository equals the execution repository. Prefer CHECK_LOOKUP_GH_TOKEN (github.token) whenever GH_REPOSITORY equals GITHUB_REPOSITORY, keeping the configured chain for cross-repository dispatch lookups. Same credential-selection gap family as #505. Co-Authored-By: Claude Fable 5 --- .github/workflows/opencode-review.yml | 8 ++++++++ tests/test_opencode_agent_contract.py | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index e88cd0bfa..d1d61b583 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -6109,6 +6109,14 @@ jobs: local output_file="$1" local pr_json head_ref scan_token lookup_error_file scan_token="${CODE_SCANNING_GH_TOKEN:-${GH_TOKEN:-}}" + if [ "${GH_REPOSITORY:-}" = "${GITHUB_REPOSITORY:-}" ] && [ -n "${CHECK_LOOKUP_GH_TOKEN:-}" ]; then + # Same-repository lookup: prefer the runner token, which carries this + # job's security-events: read permission. The OpenCode app token has no + # security_events permission, so with no PAT configured the configured + # chain 403s the code-scanning read and the model-unavailable evidence + # fallback is silently skipped on every eligible PR. + scan_token="${CHECK_LOOKUP_GH_TOKEN}" + fi if [ -z "$scan_token" ]; then printf '::warning::Open code-scanning alert lookup skipped because no target-repository read token was configured.\n' >&2 return 1 diff --git a/tests/test_opencode_agent_contract.py b/tests/test_opencode_agent_contract.py index d543bb728..a3f64d913 100644 --- a/tests/test_opencode_agent_contract.py +++ b/tests/test_opencode_agent_contract.py @@ -651,6 +651,18 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent(): assert "CODE_SCANNING_TOKEN_SOURCE" in workflow assert 'GH_TOKEN="$scan_token" timeout "$(check_lookup_api_timeout_seconds)s"' in workflow assert "Open code-scanning alert lookup skipped because no target-repository read token" in workflow + # Same-repository code-scanning reads must prefer the runner token: the job + # grants it security-events: read, while the OpenCode app token has no + # security_events permission and 403s the read, silently skipping the + # model-unavailable evidence fallback. + code_scanning_lookup = workflow.split("collect_open_code_scanning_alerts()", 1)[1].split( + "publish_blockers_after_model_unavailable()", 1 + )[0] + assert ( + '[ "${GH_REPOSITORY:-}" = "${GITHUB_REPOSITORY:-}" ] && [ -n "${CHECK_LOOKUP_GH_TOKEN:-}" ]' + in code_scanning_lookup + ) + assert 'scan_token="${CHECK_LOOKUP_GH_TOKEN}"' in code_scanning_lookup assert "production source 또는 package manifest 변경이 없습니다" not in workflow assert "needs.coverage-evidence.result != 'cancelled'" in workflow assert "request_changes_for_coverage_evidence_failure" in workflow