Skip to content

Fix validate-and-render: switch to pull_request_target for fork PR write access - #51

Merged
jchen0506 merged 4 commits into
mainfrom
copilot/fix-failing-github-actions-job
Jul 31, 2026
Merged

Fix validate-and-render: switch to pull_request_target for fork PR write access#51
jchen0506 merged 4 commits into
mainfrom
copilot/fix-failing-github-actions-job

Conversation

Copilot AI commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

The validate-and-render job was failing with HTTP 403 on the "Post PR comment" step whenever a PR came from a fork. GitHub silently restricts GITHUB_TOKEN to read-only for pull_request events from forks, regardless of what permissions: declares.

Changes

  • pull_requestpull_request_target — runs in the base-repo context, so declared issues: write / pull-requests: write permissions are always honoured, including for fork PRs.
  • Explicit ref: head.sha on checkoutpull_request_target defaults to checking out the base branch; this restores the PR's actual content.
  • New "Restore trusted scripts" step — immediately after checkout, all executable paths (scripts/, templates/, template.yaml, paths.yml, index.html, theme.css) are overwritten from the base branch SHA. Only lesson YAML data files from the fork remain, and they are only parsed, never executed.
- name: Checkout PR content
  uses: actions/checkout@v4
  with:
    ref: ${{ github.event.pull_request.head.sha }}
    fetch-depth: 0

- name: Restore trusted scripts and config from base branch
  run: |
    git fetch origin ${{ github.event.pull_request.base.sha }}
    git checkout ${{ github.event.pull_request.base.sha }} -- \
      scripts/ templates/ template.yaml paths.yml index.html theme.css

…cess

The job was failing with HTTP 403 when trying to post a PR comment
because PR #50 was a fork PR (dsirianni/portal → act-cms/portal).
With the `pull_request` trigger, GitHub's GITHUB_TOKEN is read-only
for fork PRs regardless of the declared `issues: write` permission.

Fix: switch to `pull_request_target`, which runs in the base-repo
context and always honours the declared permissions.

Security: after checking out the PR head content, all executable files
(scripts/, templates/, template.yaml, paths.yml, index.html, theme.css)
are restored from the trusted base branch SHA. Only the lesson YAML
data files from the fork are used, and those are only parsed, not
executed.
Copilot AI changed the title [WIP] Fix the failing GitHub Actions job validate-and-render Fix validate-and-render: switch to pull_request_target for fork PR write access Jul 31, 2026
Copilot AI requested a review from jchen0506 July 31, 2026 21:09
jchen0506 and others added 2 commits July 31, 2026 17:30
Fixes the HTTP 403 when posting the check summary on fork PRs, without
granting a write-scoped token to a job that runs the PR author's code.

pr-check.yml goes back to `pull_request` with `contents: read` only. It
still checks out and runs the fork's scripts/ and templates/, but now
holds a token that cannot write anything. Instead of posting a comment
it uploads the rendered body as the `pr-check-comment` artifact.

pr-comment.yml is new: it runs on `workflow_run` after the check
completes, so it executes in the base-repo context with a writable
token. It never checks out PR content — it only downloads the artifact
and posts its text.

This replaces the `pull_request_target` approach, which was not safe.
`git checkout <base> -- scripts/ templates/` overwrites files tracked in
base but never deletes files the fork *added*, so a fork could drop in
scripts/yaml.py (shadows PyYAML — sys.path[0] is the script's own
directory) or templates/platforms/<name>.html (picked up by the platform
glob and included by a non-sandboxed Jinja env) and run arbitrary code
with repo-write credentials. Reverting scripts/, templates/, paths.yml,
index.html and theme.css to base also meant PRs touching build
infrastructure were validated against base — a green check that tested
none of the submitted change — and a lesson rename plus paths.yml edit
would fail on base's now-dangling lesson ID.

The artifact is treated as untrusted throughout: the body is posted
verbatim and truncated to 60000 chars, the PR number is resolved from
event data first and the artifact's claim is honoured only when that
PR's head SHA matches the run's, and only a Bot-authored comment is
updated so a planted marker cannot hijack the summary.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The paths filter matches '**/*.yml', so a PR that only edits a workflow
triggers this check and then fails it with "move it into lessons/" —
which is what happened to this PR. CI config is not a lesson submission.

Misnamed lesson files (lessons/*.yaml, lessons/*.yml.yaml) and stray
YAML elsewhere in the tree are still flagged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@jchen0506 jchen0506 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

fix no_permission issue when submitting PR from a fork

@jchen0506
jchen0506 marked this pull request as ready for review July 31, 2026 21:35
@jchen0506
jchen0506 merged commit 3309041 into main Jul 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants