Skip to content

security: Ci/fix validate workflow#392

Open
qtipbera wants to merge 8 commits into
mainfrom
ci/fix-validate-workflow
Open

security: Ci/fix validate workflow#392
qtipbera wants to merge 8 commits into
mainfrom
ci/fix-validate-workflow

Conversation

@qtipbera
Copy link
Copy Markdown
Contributor

This PR splits validate.yml into two workflows to fix a secret exfiltration
vulnerability in the pull_request_target trigger.

The problem

The current validate.yml runs on pull_request_target (which has access to
repo secrets) and checks out fork code into ./head. Any job in that workflow
can read secrets like CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_IMAGES_API_TOKEN,
and GITHUB_TOKEN. A malicious fork PR could modify validation scripts to
exfiltrate these secrets during CI. The workflow is currently disabled for
this reason.

The fix

validate.yml (pull_request_target, zero secrets):

  • schema, format, images, coingecko, pyth, data-consistency — all run
    against fork code with no secrets in scope
  • Packages changed asset files as artifacts for the upload workflow
  • Saves PR metadata (number, head SHA) as artifact

post-validate.yml (workflow_run, has Cloudflare secrets):

  • Triggers after Validate completes successfully
  • Downloads asset artifact and PR metadata from the triggering run
  • Uploads to Cloudflare using base branch scripts only
  • Never checks out fork code

PR metadata is passed via artifact instead of workflow_run.pull_requests[]
because that array is empty for fork PRs (known GitHub limitation).

Additional fixes

  • Cache key glob: changed from **/pnpm-lock.yaml to pnpm-lock.yaml.
    The ** glob matched lockfiles in subdirectories, meaning a fork could
    influence the cache key by adding a lockfile in a nested path.

  • Unused secrets removed: BERACHAIN_HUB_API_TOKEN and
    BERACHAIN_HUB_API_BASE_URL removed from data-consistency. Confirmed
    unused via source audit of @berachain/berajs@0.1.0 — getApolloClient
    reads config from @berachain/config, not environment variables.

  • persist-credentials: false added to all fork checkout steps.

  • head.ref → head.sha on all fork checkouts to prevent TOCTOU race
    conditions.

After merge

Re-enable the Validate workflow in the Actions UI.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens CI by separating fork-controlled validation work from secret-dependent Cloudflare uploads, mitigating secret exfiltration risks stemming from pull_request_target running untrusted fork code.

Changes:

  • Split the existing validation pipeline into a no-secrets Validate workflow (runs on pull_request_target) and a secret-bearing Post-Validate workflow (runs on workflow_run).
  • Pass PR metadata and (optionally) changed assets from ValidatePost-Validate via short-lived artifacts, and remove Cloudflare upload steps from the fork-processing workflow.
  • Pin GitHub Actions to SHAs, tighten fork checkout behavior (head.sha, persist-credentials: false), and adjust the pnpm cache key to avoid nested-lockfile influence.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
.github/workflows/validate.yml Removes secret-dependent upload logic, adds artifact packaging for PR info/assets, pins actions, and hardens fork checkout + cache keying.
.github/workflows/post-validate.yml New workflow_run-driven uploader that downloads artifacts and performs Cloudflare uploads using base-branch scripts with secrets isolated.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/post-validate.yml Outdated
Comment thread .github/workflows/post-validate.yml
Comment thread .github/workflows/validate.yml Outdated

This comment was marked as resolved.

This comment was marked as resolved.

@qtipbera
Copy link
Copy Markdown
Contributor Author

Note: this PR supersedes #391 (ci/pin-actions-to-sha). Both modify validate.yml — if #391 merges first, this branch will conflict.

This PR is the superset: it includes all of #391's changes (SHA pinning, node24 action upgrades, persist-credentials: false, ref: base.sha on base checkouts) plus the security split, cache key hardening, and unused secret removal. Recommend merging this first and closing #391.

qtipbera and others added 5 commits May 26, 2026 13:24
rebasing 392 to main after merge of 391
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: qtipbera <194121515+qtipbera@users.noreply.github.com>
@qtipbera qtipbera force-pushed the ci/fix-validate-workflow branch from af5b450 to 9503eba Compare May 26, 2026 17:28
@qtipbera
Copy link
Copy Markdown
Contributor Author

@bearpong #395 should unblock this PR, but requires admin review and bypass

@bearpong
Copy link
Copy Markdown
Collaborator

@qtipbera, #395 merged. Please let's verify this PR works as expected before merging this

@qtipbera
Copy link
Copy Markdown
Contributor Author

@bearpong All checks green:

  • schema ✅
  • format ✅
  • data-consistency ✅
  • detect-changes ✅
  • coingecko ✅
  • pyth ✅
  • images ✅
  • upload-assets ⏭️ (skipped — no asset changes in this PR, expected)
  • semgrep ✅

This is running against main's workflow (via pull_request_target), which now includes the node24 upgrades (#391), lockfile fix (#393), and setup-node cache fix (#395). The validation ran against fork checkout code in ./head and all jobs passed.

Ready for review.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants