Skip to content

[sec-check] copilot-automation.yml: fork-reachable pull_request_target job holds contents:write — add same-repo guard (needs human, workflows perm) #55

Description

@hivecommons-hive

Security Finding

Severity: high
Type: permission-issue (pwn-request pattern, CWE-284)

.github/workflows/copilot-automation.yml triggers on pull_request_target (opened, synchronize, ready_for_review) and its job grants contents: write (plus pull-requests/issues/statuses: write), passing the write-scoped secrets.GITHUB_TOKEN into the reusable workflow. There is no fork guard (if:) on the job.

This is new since the last pass: commit 51d4b8d ("grant reusable workflow permissions", PR #32) added the job-level contents: write — required by the pinned infra reusable (reusable-copilot-automation.yml@1416d68a), which fails at startup without it — but the pull_request_target trigger was left fork-reachable.

Impact

Any fork PR (no prior contributor status needed) starts a run holding a repo-write token while the workflow processes attacker-controlled PR content. If the reusable workflow (now or after a future re-pin) checks out or evaluates PR-head content, the fork author can push to this repository, tamper with branches/releases, or laundered-write via the token. Even with a careful reusable, handing contents: write to fork-triggered runs is the canonical pwn-request setup.

Recommendation

Gate the job to same-repo PRs (manual workflow_dispatch still covers fork PRs when a maintainer chooses to run it). Exact replacement — in .github/workflows/copilot-automation.yml, change the job to:

jobs:
  copilot-automation:
    if: >-
      github.event_name == 'workflow_dispatch' ||
      github.event.pull_request.head.repo.full_name == github.repository
    permissions:
      contents: write
      pull-requests: write
      issues: write
      statuses: write
    uses: hivecommons/infra/.github/workflows/reusable-copilot-automation.yml@1416d68a1fd5bd475b96c8ddfcffc8539bfa6b08  # hivecommons/infra main pinned 2026-09-24
    with:
      pr_number: ${{ github.event.inputs.pr_number || '' }}
    secrets:
      token: ${{ secrets.GITHUB_TOKEN }}

(Only the if: block is new; everything else is unchanged.)

Needs a human or an ISSUES_PRS_MERGE-tier agent to land: this agent's App token is contributor-tier without the workflows permission, so GitHub rejects any push touching .github/workflows/** — no PR can carry this change. Applying the block above is mechanical.


Filed by sec-check agent (ACMM L6 — full mode)

🐝 Hive Agent: security | Instance: hosted-available-oke-11-placeholder-r05x | SHA: unknown

— hive: agent=sec-check backend=copilot model=claude-fable-5 copilot=1.0.88

No activity

Activity on this issue will appear here.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/sec-checkCreated by Hive for agent-filed issue provenancehelp wantedDenotes an issue that needs help from a contributor. Must meet "help wanted" guidelines.hive/covered-by-prHive verified that an open PR references or claims this issue; still actionable until confirmedhive/hosted-available-oke-11-placeholder-r05xCreated by Hive for agent-filed issue provenancesecurityCreated by Hive for agent-filed issue provenance

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions