Skip to content

ci: re-enable fork PR integration runs blocked by actions/checkout v7 - #1216

Merged
njbrake merged 2 commits into
mainfrom
fix/integration-fork-checkout
Aug 3, 2026
Merged

ci: re-enable fork PR integration runs blocked by actions/checkout v7#1216
njbrake merged 2 commits into
mainfrom
fix/integration-fork-checkout

Conversation

@njbrake

@njbrake njbrake commented Aug 3, 2026

Copy link
Copy Markdown
Member

Description

Labeling a fork PR with run-integration-tests currently fails before any test runs.

actions/checkout v7.0.0 began refusing to check out fork PR code from a pull_request_target workflow (actions/checkout#2454). tests-integration.yaml picked that up through the v6 to v7 dependabot bump in #1157, merged 2026-07-14. Since then, determine-jobs-to-run dies at checkout with:

##[error]Refusing to check out fork pull request code from a 'pull_request_target' workflow.

should_run_integration is then never set, so both run-integration-tests and run-local-integration-tests are skipped. Total runtime about 12 seconds.

This went unnoticed for three weeks because nothing in CI covers the path and every labeled PR in between was from a branch in this repo, where the fork guard does not apply. It surfaced on #1202, the first fork PR to get the label since the bump.

What this changes

  1. allow-unsafe-pr-checkout: true on the three checkout steps that pass a fork head (lines 63, 82, 146). These are the only checkout steps in the repo that do so; pr-template-check.yml is the other pull_request_target workflow and deliberately never checks out fork code.
  2. A comment at the top of the file recording why the opt-in is acceptable here, what the label gate does and does not cover, and why the ref: inputs must not be dropped to dodge the check.
  3. permissions: narrowed. The workflow no longer grants pull-requests: write globally; only remove-label needs it, so it is granted at that job. The jobs that execute fork code are left with contents: read.

On the security tradeoff

The guard is flagging a real pattern rather than a false positive: pull_request_target runs with this repo's secrets, and the integration job needs roughly 25 provider API keys. The mitigation is the existing gate. The run only fires when someone with write access applies the label, and remove-label strips it immediately so each run is a fresh deliberate act. What the gate does not cover is that the keys are readable by whatever code runs, so applying the label is a credential-trust decision and the diff needs reading first, tests/ and conftest.py included. That is written into the file so the next person meets it before the next bump.

Bumping the action forward is not an alternative. v7.0.1 is the newest release and the block is intentional from v7 on; its only change here was to skip the check when ref is unset, which does not apply since we set it. Pinning back to v6 would work but hides the risk and invites dependabot to reopen it.

PR Type

  • 🚦 Infrastructure

Relevant issues

Found while reviewing #1202.

Checklist

  • I understand the code I am submitting.
  • I have added unit tests that prove my fix/feature works
  • I have run this code locally and verified it fixes the issue.
  • New and existing tests pass locally
  • Documentation was updated where necessary
  • I have read and followed the contribution guidelines
  • AI Usage:
    • No AI was used.
    • AI was used for drafting/refactoring.
    • This is fully AI-generated.

Notes on the two unchecked boxes. There are no unit tests, because a workflow trigger path is not reachable from pytest; the verification is the run itself, which needs this merged to main before a labeled fork PR can exercise it. What was verified locally: the YAML parses and resolves to the intended per-job permissions, pre-commit passes on the file, and allow-unsafe-pr-checkout was confirmed as the correct input name and spelling by reading action.yml at the v7 tag rather than trusting the error message.

AI Usage Information

  • AI Model used: Claude Opus 5

  • AI Developer Tool used: Claude Code

  • Any other info you'd like to share: Diagnosed and written by Claude while reviewing fix(gemini): map candidate.finish_reason to the OpenAI vocabulary #1202, under my direction. The security tradeoff and the choice to opt in rather than pin back to v6 are my calls.

  • I am an AI Agent filling out this form (check box if true)

Summary by CodeRabbit

  • Tests
    • Updated integration-test automation to run against the intended pull request revisions.
    • Added clearer safeguards and more narrowly scoped permissions for test-related workflow actions.
    • Restricted certain automated actions to approved, label-gated scenarios, improving the security and reliability of integration testing.
    • Documented the workflow’s checkout controls to make test execution behaviour clearer and more consistent.

actions/checkout v7.0.0 began refusing to check out fork PR code from a
pull_request_target workflow (actions/checkout#2454). tests-integration.yaml
picked that up via the v6 to v7 dependabot bump in #1157, so since 2026-07-14
labeling a fork PR fails at the checkout step in determine-jobs-to-run and both
test jobs are skipped. Found on #1202, the first fork PR labeled since the bump.

Set allow-unsafe-pr-checkout: true on the three checkout steps, with a comment
at the top of the file recording why the opt-in is acceptable here and what it
does not cover. Dropping the ref: inputs would also satisfy the action, but it
would check out the base branch and silently test main instead of the PR.

Also narrow permissions: the workflow no longer grants pull-requests: write
globally. Only remove-label needs it, so it is granted at that job, leaving the
jobs that execute fork code with contents: read.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@njbrake
njbrake temporarily deployed to integration-tests August 3, 2026 12:43 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The integration workflow documents its unsafe PR-head checkout model, restricts pull-requests: write to remove-label, and enables explicit PR-head checkouts for three integration-test jobs.

Changes

Integration workflow security

Layer / File(s) Summary
Security controls and documentation
.github/workflows/tests-integration.yaml
The workflow documents the maintainer-only label gate, residual secret exposure, PR-head ref requirement, and restricted permissions. pull-requests: write is scoped to remove-label.
Unsafe PR-head checkouts
.github/workflows/tests-integration.yaml
The provider-detection, hosted integration-test, and local integration-test jobs set allow-unsafe-pr-checkout: true, disable persisted credentials, and retain the pull-request head SHA.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the CI change that re-enables fork pull request integration runs after the actions/checkout v7 block.
Description check ✅ Passed The description follows the template, explains the cause and security trade-off, identifies the changes, and records verification details.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/integration-fork-checkout

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
see 34 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/tests-integration.yaml:
- Around line 26-34: Update the workflow’s label-trigger authorization gate so
integration-test jobs run only when the actor who applied run-integration-tests
has write-level or higher repository permission; apply this check alongside the
existing github.event.label.name conditions before enabling fork-code jobs.
Preserve the fresh-label approval behavior, or explicitly revise the adjacent
trust-model comment if the workflow intentionally permits triage-level authors.
- Around line 92-95: Replace the mutable actions/checkout@v7 reference with the
reviewed full 40-character commit SHA for v7 at all checkout steps in
.github/workflows/tests-integration.yaml: lines 92-95, 114-117, and 181-184.
Preserve each step’s existing with configuration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1f150958-d204-4252-aae5-b468755733cc

📥 Commits

Reviewing files that changed from the base of the PR and between fac5aca and 6bfd4b6.

📒 Files selected for processing (1)
  • .github/workflows/tests-integration.yaml

Comment on lines +26 to +34
# 1. pull_request_target fires on types: [labeled], and every job is gated on the label being
# run-integration-tests, so nothing runs until someone with write access applies it. A
# contributor cannot label their own PR. Applying the label means "I have read this diff
# and I am willing to run it against our keys", so treat it as a credential-trust decision,
# not just a request for CI minutes.
# 2. remove-label strips the label immediately, so each run needs a fresh, deliberate act. A
# later push to the same PR cannot silently reuse an earlier approval.
# 3. The jobs that execute fork code hold only contents: read (see below), so a hostile PR
# cannot write to the repository or to pull requests.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow =="
sed -n '1,220p' .github/workflows/tests-integration.yaml 2>/dev/null || true

echo
echo "== label-related workflow elements =="
python3 - <<'PY'
from pathlib import Path
p=Path('.github/workflows/tests-integration.yaml')
text=p.read_text()
for i,line in enumerate(text.splitlines(),1):
    if any(s in line for s in ['github.event_label', 'if: github', 'label', 'permissions:', 'pull_request_target', 'actions/checkout']):
        print(f'{i}: {line}')
PY

Repository: mozilla-ai/any-llm

Length of output: 12752


🌐 Web query:

GitHub repository roles triage can add and remove labels pull requests permissions

💡 Result:

In GitHub repositories, users with the Triage role have the permission to apply and dismiss labels on issues and pull requests [1][2][3]. The Triage role is specifically designed for contributors who need to proactively manage issues, discussions, and pull requests without requiring full write access [1][4]. While users with Triage access can apply or dismiss existing labels, they do not have the permission to create, edit, or delete the labels themselves; these actions are restricted to users with Write access or higher [1][2][3]. Summary of label-related permissions by role: - Triage: Can apply and dismiss (remove) labels [1][2]. - Write (and higher): Can apply, dismiss, create, edit, and delete labels [1][2]. Additionally, users with Triage access can perform other tasks such as closing, reopening, and assigning issues and pull requests [1][3]. It is also important to distinguish these permission-based labels from "repository member role labels" (such as "First-time contributor" or "Member"), which are system-generated indicators visible in the pull request list view to help maintainers assess contributor context [5].

Citations:


🌐 Web query:

GitHub Actions pull_request_target run-integration-tests check github.event.label.name triage

💡 Result:

Using the pull_request_target trigger to run integration tests based on a label is a common pattern to securely execute workflows with elevated privileges (like access to secrets) for pull requests, particularly those from forks [1][2][3]. Because pull_request_target workflows run in the context of the repository's base branch (rather than the untrusted fork's head), they are protected from direct execution of malicious code, but they remain a high-value target for security exploits if not handled carefully [4][5][6]. To implement this securely, follow these guidelines: 1. Workflow Configuration: Configure the workflow to trigger on the labeled activity type [2][7][8]. on: pull_request_target: types: - labeled 2. Job-Level Security Checks: Always include an if conditional at the job level to ensure the workflow only executes when the specific authorized label is present [2][9][3]. This prevents the workflow from running for unauthorized pull requests or other label changes [7]. jobs: run-integration-tests: if: github.event.label.name == 'integration-test' runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: # Important: Fetch the specific PR head to test the changes ref: ${{ github.event.pull_request.head.sha }} 3. Security Best Practices: * Principle of Least Privilege: Do not assume that because the workflow file is in the base branch, it is automatically safe. Avoid running untrusted code from the pull request (e.g., shell scripts, dependency installers) unless you have carefully audited those steps [4][6]. * Checkout Safety: As of June 2026, actions/checkout has updated default behaviors to block insecure checkouts of fork PRs in pull_request_target workflows [10]. If you must check out the fork's code, you are responsible for ensuring that the code is not executed in a privileged way [4][10]. * Manual Verification: Many teams require that a maintainer manually applies the label after reviewing the PR, effectively acting as an approval gate before the workflow runs [2][3][7]. By gating the execution on a specific label and ensuring the workflow logic is audit-focused, you create a controlled environment where elevated privileges (secrets/write access) are only used on code that has been reviewed and cleared for testing [5][1].

Citations:


Enforce the write-access gate for the label approval.

This workflow states that only someone with write access should apply run-integration-tests, but the job conditions only check github.event.label.name. Repository users with only triage access can apply that label on pull requests, so the label gate does not satisfy the documented credential-trust boundary.

Require a write-or-higher label-author for this workflow before enabling the fork-code jobs, or explicitly update the workflow comment and trust model to allow every label author to run fork code with provider API keys.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/tests-integration.yaml around lines 26 - 34, Update the
workflow’s label-trigger authorization gate so integration-test jobs run only
when the actor who applied run-integration-tests has write-level or higher
repository permission; apply this check alongside the existing
github.event.label.name conditions before enabling fork-code jobs. Preserve the
fresh-label approval behavior, or explicitly revise the adjacent trust-model
comment if the workflow intentionally permits triage-level authors.

Comment on lines 92 to +95
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
allow-unsafe-pr-checkout: true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow relevant lines =="
sed -n '85,100p;108,120p;175,187p' .github/workflows/tests-integration.yaml 2>/dev/null || true

echo
echo "== all action/checkout occurrences in workflow =="
rg -n 'uses:\s*actions/checkout@|allow-unsafe-pr-checkout|pull_request.head.sha' .github/workflows/tests-integration.yaml || true

echo
echo "== repository files around workflow =="
git ls-files .github/workflows || true

Repository: mozilla-ai/any-llm

Length of output: 2774


🌐 Web query:

GitHub Actions security hardening immutable action refs actions/checkout pin to full commit SHA documentation

💡 Result:

To harden GitHub Actions security, it is highly recommended to pin all action references to their full 40-character commit SHA [1][2]. This practice ensures immutability, preventing a compromised repository from silently pushing malicious updates to tags or branches that your workflows rely on [3][4][5]. How to Pin Actions to a Commit SHA To implement this, identify the full commit SHA of the action version you intend to use and replace the tag/branch reference in your workflow's uses statement [4]. It is best practice to include the original version tag as a trailing comment to maintain human readability and enable automated tools like Dependabot or Renovate to track updates [3][6][5]. Example: - uses: actions/checkout@v4 becomes: - uses: actions/checkout@b4ffde6 # v4.1.7 Important Considerations: 1. Canonical Repository Verification: Ensure that the SHA you use originates from the action's official, canonical repository, not a fork [1][6]. 2. Enforcement Policies: Administrators can enforce SHA pinning at the enterprise, organization, and repository levels [1][7]. When enabled, workflows attempting to use mutable references (like tags or branches) will fail [8]. 3. Automated Upgrades: Tools like Dependabot and Renovate support SHA pinning and will continue to propose dependency update pull requests, ensuring you can update to newer versions deliberately after review [3][2][5]. 4. Supply Chain Defense: This approach mitigates risks from tag-moving attacks (where an attacker compromises an account and points a tag to malicious code) [3][6]. For additional security, you may also consider using tools that automatically scan your workflows to ensure all actions are pinned to full SHAs [9]. Official GitHub documentation provides further guidance on securing workflows and managing these security policies [1][10][8].

Citations:


Pin actions/checkout to an immutable commit SHA.

actions/checkout@v7 is a mutable tag, so it can change under repository control. Use the reviewed full 40-character commit SHA for the required v7 release at each checkout step.

  • .github/workflows/tests-integration.yaml#L92-L95
  • .github/workflows/tests-integration.yaml#L114-L117
  • .github/workflows/tests-integration.yaml#L181-L184
🧰 Tools
🪛 zizmor (1.28.0)

[warning] 92-95: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 92-92: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

📍 Affects 1 file
  • .github/workflows/tests-integration.yaml#L92-L95 (this comment)
  • .github/workflows/tests-integration.yaml#L114-L117
  • .github/workflows/tests-integration.yaml#L181-L184
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/tests-integration.yaml around lines 92 - 95, Replace the
mutable actions/checkout@v7 reference with the reviewed full 40-character commit
SHA for v7 at all checkout steps in .github/workflows/tests-integration.yaml:
lines 92-95, 114-117, and 181-184. Preserve each step’s existing with
configuration.

Source: Linters/SAST tools

Two fixes to the security note and checkout steps added in the previous commit,
both raised by CodeRabbit on #1216.

The note claimed the label gate requires write access. It does not: GitHub's
triage role can apply and dismiss labels, so anyone at triage or above can start
a run. State the actual boundary, and record that the workflow does not verify
the labeler's permission level so the next person can decide whether to add that
check. Also note that determine-jobs-to-run executes
./.github/actions/determine-jobs from the fork's tree, so that composite action
is fork-controlled and is not a safe place for trusted logic.

Set persist-credentials: false on all three checkout steps. The default leaves
the token in .git/config, which is readable by the fork code these jobs then
run. Nothing in these jobs uses git after checkout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@njbrake
njbrake temporarily deployed to integration-tests August 3, 2026 12:48 — with GitHub Actions Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/tests-integration.yaml:
- Around line 33-44: Update the residual-risks documentation in the workflow
comments to explicitly state that jobs retain access to the github.token context
through action steps, including the fork-controlled determine-jobs-to-run
composite action, despite persist-credentials: false. Keep the contents: read
permissions and existing checkout guidance unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 370f703b-ffc8-4bbb-a5e8-6335fff7399d

📥 Commits

Reviewing files that changed from the base of the PR and between 6bfd4b6 and 94fd2f6.

📒 Files selected for processing (1)
  • .github/workflows/tests-integration.yaml

Comment on lines +33 to +44
# 3. The jobs that execute fork code hold only contents: read (see below), and check out with
# persist-credentials: false so the token is not left in .git/config for that code to read.
#
# Residual risks the gate does NOT cover:
# - The provider API keys are readable by whatever code runs. Read the diff, with attention to
# tests/ and conftest.py, before applying the label.
# - The gate is "any member who can label", not "write access". GitHub's triage role can apply
# and dismiss labels without write access, so anyone at triage or above can start a run. This
# workflow does not verify the labeler's permission level; if triage is ever granted to
# someone who should not reach the provider keys, add an explicit check on the label author.
# - determine-jobs-to-run runs ./.github/actions/determine-jobs from the checked-out tree, so
# that composite action is fork-controlled too. It is not a safe place to put trusted logic.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## workflow excerpt"
sed -n '1,150p' .github/workflows/tests-integration.yaml 2>/dev/null || true

echo
echo "## determine-jobs action files"
if [ -d .github/actions/determine-jobs ]; then
  find .github/actions/determine-jobs -maxdepth 3 -type f | sort | while read -r f; do
    echo "--- $f"
    sed -n '1,220p' "$f"
  done
fi

echo
echo "## checkout invocations and github.token usages"
rg -n --hidden --glob '!node_modules/**' --glob '!dist/**' 'actions/checkout|persist-credentials|github\.token|GITHUB_TOKEN' .github tests conftest.py 2>/dev/null || true

Repository: mozilla-ai/any-llm

Length of output: 11307


🌐 Web query:

actions/checkout persist-credentials false github token context available to actions documentation

💡 Result:

When using the actions/checkout action in GitHub Actions, the persist-credentials input (which defaults to true) controls whether the action automatically configures the local Git environment with a GitHub token for authenticated Git commands [1][2]. By default, actions/checkout automatically adds the token to the Git configuration, allowing subsequent steps in your job to perform authenticated Git operations (like git push or git pull) without needing to manually configure credentials [1][3]. If you set persist-credentials to false, the action does not store these credentials in the local Git configuration [1]. Consequently, any subsequent step requiring Git authentication will fail unless you manually handle the authentication [4]. To access and use a token when persist-credentials is set to false, you must manually provide the token to your Git commands or configure a credential helper yourself [4]. Common approaches include: 1. Manual environment variable usage: You can pass the GitHub token (typically ${{ github.token }} or a custom secret) as an environment variable to your step or script and use it in your Git commands [4]. For example: git push https://x-access-token:${{ secrets.MY_TOKEN }}@github.com/owner/repo.git 2. Manual credential configuration: You can manually configure Git to use your token within your workflow step [4]: git config --global credential.helper store echo "https://x-access-token:${{ secrets.MY_TOKEN }}@github.com" > ~/.git-credentials Security Note: Setting persist-credentials to false is often recommended as a security best practice to prevent arbitrary subsequent steps from implicitly accessing the repository token [5]. However, ensure your workflow adheres to the principle of least privilege by setting appropriate repository permissions for the GITHUB_TOKEN itself, rather than relying solely on this configuration [5].

Citations:


Document the remaining GITHUB_TOKEN exposure.

persist-credentials: false prevents checkout from persisting Git credentials, but the job still exposes the github.token context to action steps, including the fork-controlled composite action. Keep the jobs at contents: read and list this as a residual risk so reviewers do not rely on checkout alone to prevent token access.

Suggested documentation update
 #   - The provider API keys are readable by whatever code runs. Read the diff, with attention to
 #     tests/ and conftest.py, before applying the label.
+#   - `persist-credentials: false` prevents checkout credential persistence, but does not remove
+#     the job's `github.token` context from fork-controlled action steps.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# 3. The jobs that execute fork code hold only contents: read (see below), and check out with
# persist-credentials: false so the token is not left in .git/config for that code to read.
#
# Residual risks the gate does NOT cover:
# - The provider API keys are readable by whatever code runs. Read the diff, with attention to
# tests/ and conftest.py, before applying the label.
# - The gate is "any member who can label", not "write access". GitHub's triage role can apply
# and dismiss labels without write access, so anyone at triage or above can start a run. This
# workflow does not verify the labeler's permission level; if triage is ever granted to
# someone who should not reach the provider keys, add an explicit check on the label author.
# - determine-jobs-to-run runs ./.github/actions/determine-jobs from the checked-out tree, so
# that composite action is fork-controlled too. It is not a safe place to put trusted logic.
# 3. The jobs that execute fork code hold only contents: read (see below), and check out with
# persist-credentials: false so the token is not left in .git/config for that code to read.
#
# Residual risks the gate does NOT cover:
# - The provider API keys are readable by whatever code runs. Read the diff, with attention to
# tests/ and conftest.py, before applying the label.
# - `persist-credentials: false` prevents checkout credential persistence, but does not remove
# the job's `github.token` context from fork-controlled action steps.
# - The gate is "any member who can label", not "write access". GitHub's triage role can apply
# and dismiss labels without write access, so anyone at triage or above can start a run. This
# workflow does not verify the labeler's permission level; if triage is ever granted to
# someone who should not reach the provider keys, add an explicit check on the label author.
# - determine-jobs-to-run runs ./.github/actions/determine-jobs from the checked-out tree, so
# that composite action is fork-controlled too. It is not a safe place to put trusted logic.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/tests-integration.yaml around lines 33 - 44, Update the
residual-risks documentation in the workflow comments to explicitly state that
jobs retain access to the github.token context through action steps, including
the fork-controlled determine-jobs-to-run composite action, despite
persist-credentials: false. Keep the contents: read permissions and existing
checkout guidance unchanged.

@njbrake
njbrake merged commit dd21d2a into main Aug 3, 2026
12 checks passed
@njbrake
njbrake deleted the fix/integration-fork-checkout branch August 3, 2026 13:03
@github-actions github-actions Bot added the 1.24.0 Included in release 1.24.0 label Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1.24.0 Included in release 1.24.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant