Security Finding
Severity: medium
Type: unsafe-pattern (workflow / pwn-request surface)
.github/workflows/pr-verifier.yml runs on pull_request_target: [opened, edited, synchronize, reopened], passes secrets: inherit to the reusable workflow, and grants checks: write on the base-repo GITHUB_TOKEN — with no guard on github.event.pull_request.head.repo.fork and no restriction on which forked-PR revisions may reach the reusable workflow.
on:
pull_request_target:
types: [opened, edited, synchronize, reopened]
permissions:
checks: write
pull-requests: read
jobs:
verify:
uses: kubestellar/infra/.github/workflows/reusable-pr-verifier.yml@220beeeb8dae67e2fd8e89338ada8144609fc6ef # main
secrets: inherit
Two hardening gaps:
secrets: inherit hands the entire org/repo secret set to the reusable workflow on every fork-PR event. Even though the reusable workflow is pinned by SHA (good), any future step that echoes an environment value, writes a debug artifact, or interpolates a secret into a run: block executed from PR-derived text becomes an exfil path — and fork PRs (including edited) provide untrusted input.
- No fork guard.
pull_request_target runs with base-repo permissions on fork PRs by design. Combined with checks: write, the check-run text is attacker-controllable input territory unless the reusable workflow scrubs the PR title/body it consumes — same pwn-request class as homebrew-tap#378 and console-marketplace#619.
The pinned SHA 220beeeb… mitigates supply-chain risk on the reusable workflow itself; this finding is about the caller-side surface.
Impact
If the reusable workflow ever evaluates PR-derived text in a shell context (title/body → run:), an attacker opening a fork PR can:
- forge or manipulate PR check-run status via
checks: write on the base repo;
- exfiltrate any inherited secret through log injection or an artifact upload.
Scope is the entire secret bundle available at the org/repo level, not just GITHUB_TOKEN.
Recommendation
Two concrete hardenings, in order of impact:
- Pass only the secrets the reusable workflow actually needs instead of
secrets: inherit. If it only needs GITHUB_TOKEN, drop the line entirely (that token is provided automatically).
- Explicit fork guard on the caller job so the base-repo token never runs against untrusted revisions unless required:
jobs:
verify:
if: github.event.pull_request.head.repo.full_name == github.repository
uses: kubestellar/infra/.github/workflows/reusable-pr-verifier.yml@220beeeb…
If pr-verifier must run on fork PRs (typical — it verifies title/body), then at minimum audit the reusable workflow (in kubestellar/infra) and confirm it never interpolates github.event.pull_request.title/body/head_ref into run: blocks unquoted, and never checks out the PR HEAD with credentials.
Also worth doing at the repo level: enable "Require approval for all outside collaborators" in Settings → Actions, which gates pull_request_target runs on fork PRs until a maintainer approves.
References
Filed by sec-check agent (ACMM L6 — full mode)
— hive: agent=sec-check backend=copilot model=claude-opus-4.7
Security Finding
Severity: medium
Type: unsafe-pattern (workflow / pwn-request surface)
.github/workflows/pr-verifier.ymlruns onpull_request_target: [opened, edited, synchronize, reopened], passessecrets: inheritto the reusable workflow, and grantschecks: writeon the base-repoGITHUB_TOKEN— with no guard ongithub.event.pull_request.head.repo.forkand no restriction on which forked-PR revisions may reach the reusable workflow.Two hardening gaps:
secrets: inherithands the entire org/repo secret set to the reusable workflow on every fork-PR event. Even though the reusable workflow is pinned by SHA (good), any future step that echoes an environment value, writes a debug artifact, or interpolates a secret into arun:block executed from PR-derived text becomes an exfil path — and fork PRs (includingedited) provide untrusted input.pull_request_targetruns with base-repo permissions on fork PRs by design. Combined withchecks: write, the check-run text is attacker-controllable input territory unless the reusable workflow scrubs the PR title/body it consumes — same pwn-request class as homebrew-tap#378 and console-marketplace#619.The pinned SHA
220beeeb…mitigates supply-chain risk on the reusable workflow itself; this finding is about the caller-side surface.Impact
If the reusable workflow ever evaluates PR-derived text in a shell context (title/body →
run:), an attacker opening a fork PR can:checks: writeon the base repo;Scope is the entire secret bundle available at the org/repo level, not just
GITHUB_TOKEN.Recommendation
Two concrete hardenings, in order of impact:
secrets: inherit. If it only needsGITHUB_TOKEN, drop the line entirely (that token is provided automatically).kubestellar/infra) and confirm it never interpolatesgithub.event.pull_request.title/body/head_refintorun:blocks unquoted, and never checks out the PR HEAD with credentials.Also worth doing at the repo level: enable "Require approval for all outside collaborators" in Settings → Actions, which gates
pull_request_targetruns on fork PRs until a maintainer approves.References
Filed by sec-check agent (ACMM L6 — full mode)
— hive: agent=sec-check backend=copilot model=claude-opus-4.7