Skip to content

ci(landing): deploy landing via Actions so fork PRs stop failing Vercel - #1248

Merged
murdore merged 1 commit into
releasefrom
ci/landing-vercel-actions
Jul 30, 2026
Merged

ci(landing): deploy landing via Actions so fork PRs stop failing Vercel#1248
murdore merged 1 commit into
releasefrom
ci/landing-vercel-actions

Conversation

@murdore

@murdore murdore commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Problem

Every fork PR shows a red Vercel check. It is not a build failure — it is an authorization prompt. The status links to vercel.com/git/authorize?..., not to a deployment.

Vercel's docs: "when you receive a pull request from a fork of your repository, Vercel will require authorization from you or a team member to deploy the pull request… The authorization step will be skipped if the commit author is already a team member."

Confirmed 8/8 across the open PRs:

Source Vercel
same-repo (#1237, #1172) ✅ pass
fork (#1238, #1241, #1242, #1233, #1204, #1200) ❌ fail — every one

Two things make this unfixable in-repo:

  1. The gate fires before the build, so vercel.json / ignoreCommand never runs on a fork PR — no repo-side config can suppress it.
  2. The Vercel project is on a personal (Hobby) scope with gitForkProtection: true. Contributors can't be added as team members to skip the gate, and turning fork protection off would let fork code build against the project's environment — a security downgrade, not a fix.

Net effect today: every external contribution is permanently non-CLEAN, and real failures are camouflaged by a guaranteed-red check. (It doesn't block merging — Vercel isn't in required_status_checks — but it makes "is this PR green?" unreadable.)

Fix

Drive the landing deploy from Actions instead, where the trigger is ours to gate:

  • push to release touching landing/** → production deploy
  • PR from this repo touching landing/** → preview deploy + a sticky PR comment with the URL
  • PR from a fork → job is skipped, which reports neutral, not red

The if: states the intent; GitHub withholding secrets from fork pull_request runs is what actually enforces it — a fork cannot deploy even if the condition were wrong.

vercel pull fetches project settings, so rootDirectory: landing, the SvelteKit preset and the landing/vercel.json redirects keep working without being duplicated here.

Follow-up (not in this PR): once this is confirmed green, disconnect the Vercel Git integration so the two don't both deploy.

Verification

This PR modifies .github/workflows/landing-deploy.yml, which is in its own paths: filter — so it deploys itself. A preview URL commented below is the proof it works end to end.

Secrets VERCEL_TOKEN / VERCEL_ORG_ID / VERCEL_PROJECT_ID are configured on the repo. The token is scoped to this use and independently revocable.

Summary by CodeRabbit

  • New Features
    • Added an automated GitHub Actions workflow to deploy the landing site to Vercel.
    • Deploys production on release-branch pushes, and creates preview deployments for eligible pull requests.
    • Posts/updates a persistent pull request comment containing the preview URL.
    • Includes workflow concurrency handling to cancel in-progress deployments for the same ref/PR.

Copilot AI review requested due to automatic review settings July 29, 2026 19:45
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
neurolink Ready Ready Preview Jul 29, 2026 7:50pm

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

✅ Single Commit Policy - COMPLIANT

Status: Policy requirements met • 1 commit • Valid format • Ready for merge

📊 View validation details

📝 Commit Details

  • Hash: 7d14f8306da267ac383d65ca648f18702ae32139
  • Message: ci(landing): deploy landing via Actions so fork PRs stop failing Vercel
  • Author: Sachin Sharma

✅ Validation Results

  • Single commit requirement met
  • No merge commits in branch
  • Semantic commit message format verified
  • Ready for squash merge to release branch

🤖 Automated validation by NeuroLink Single Commit Enforcement

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a GitHub Actions workflow that builds and deploys the landing app to Vercel for release pushes, pull requests, and manual runs, then records the deployment URL and updates pull request preview comments.

Changes

Landing Vercel deployment

Layer / File(s) Summary
Workflow triggers and deployment job
.github/workflows/landing-deploy.yml
Adds release, pull request, and manual triggers; configures concurrency, permissions, same-repository PR execution, Node.js, and Vercel CLI setup.
Environment resolution and Vercel deployment
.github/workflows/landing-deploy.yml
Selects production or preview deployment targets, builds the landing site, deploys the prebuilt artifact, and records the deployment URL.
Pull request preview comment
.github/workflows/landing-deploy.yml
Creates or updates a marked pull request comment containing the preview URL.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant VercelCLI
  participant Vercel
  participant PullRequest
  GitHubActions->>VercelCLI: Resolve deployment target
  GitHubActions->>VercelCLI: Pull settings and build landing site
  VercelCLI->>Vercel: Deploy prebuilt artifact
  Vercel-->>GitHubActions: Return deployment URL
  GitHubActions->>PullRequest: Create or update preview URL comment
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: moving landing deployments to GitHub Actions to avoid fork PR Vercel failures.
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 ci/landing-vercel-actions

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.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

Copilot AI 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.

Pull request overview

This PR replaces Vercel’s Git integration for the landing/** site with a GitHub Actions-driven deploy workflow, so fork-based pull requests no longer show a guaranteed-red “requires authorization” Vercel status check.

Changes:

  • Added a new landing-deploy workflow that deploys production on release pushes affecting landing/**.
  • Added preview deploys for same-repo PRs affecting landing/**, and skips fork PRs to yield a neutral result instead of a failing check.
  • Posts/updates a sticky PR comment containing the preview URL.

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

Comment on lines +103 to +105
const existing = (
await github.rest.issues.listComments({ owner, repo, issue_number, per_page: 100 })
).data.find((c) => c.body && c.body.includes(marker));
@github-actions

Copy link
Copy Markdown
Contributor

Landing preview: https://neurolink-gqt5vptlw-sachin-sharmas-projects-7dbbe7a8.vercel.app

Deployed from aa9850a by the landing-deploy workflow.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@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: 3

🤖 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/landing-deploy.yml:
- Around line 58-59: Update the “Install Vercel CLI” workflow step to install an
exact validated Vercel CLI version instead of the mutable latest tag, and retain
that explicit version in the command so future upgrades require a deliberate
workflow change.
- Around line 34-36: Update the deploy job in the workflow to retain only
contents: read permission, move any PR commentary or commit-status steps into a
separate job scoped with pull-requests: write, and configure its checkout step
with persist-credentials: false.
- Around line 103-105: Update the sticky-comment lookup around
github.rest.issues.listComments to paginate through all comment pages rather
than limiting the search to one page, and only select a comment whose
c.user?.login equals github-actions[bot] in addition to containing marker.
Preserve the existing update-or-create flow using the authoritative matching
comment.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 82fbd066-614b-4cb8-96ec-2adae74c21ba

📥 Commits

Reviewing files that changed from the base of the PR and between da2356a and 993e1ff.

📒 Files selected for processing (1)
  • .github/workflows/landing-deploy.yml

Comment on lines +34 to +36
permissions:
contents: read
pull-requests: write

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 excerpt =="
sed -n '1,90p' .github/workflows/landing-deploy.yml 2>/dev/null || true

echo
echo "== checkout usages in workflows =="
rg -n "actions/checkout|permissions:|pull-requests:|persist-credentials" .github/workflows -C 2 || true

echo
echo "== git diff stat and relevant diff =="
git diff --stat || true
git diff -- .github/workflows/landing-deploy.yml | sed -n '1,160p' || true

Repository: juspay/neurolink

Length of output: 12935


🌐 Web query:

actions/checkout persist-credentials default true README

💡 Result:

In the actions/checkout GitHub Action, the persist-credentials input determines whether the action configures the provided token or SSH key within the local Git configuration [1][2]. As of July 2026, the default value for persist-credentials remains true [1][3][4]. When set to true, the action configures the authentication credentials in the local Git configuration, which allows your workflow scripts to perform authenticated Git commands (such as git push or git fetch) [1][2]. The action automatically removes these credentials during the post-job cleanup process [1][2]. While there have been community discussions and proposals to change this default to false to further enhance security—specifically to minimize the risk of accidental credential exposure—the default behavior has not been altered in the official releases [5]. If you prefer to disable this behavior for security reasons, you can explicitly set the input to false in your workflow file: - uses: actions/checkout@v4 with: persist-credentials: false

Citations:


🌐 Web query:

GitHub security hardening of Actions permissions pull-requests write contents read actions checkout

💡 Result:

To harden GitHub Actions security, you must adhere to the principle of least privilege, especially when using sensitive event triggers [1][2]. 1. Set Default Permissions to Read-Only At the organization or repository level, configure the default GITHUB_TOKEN permissions to read-only [3][4][5]. This ensures that, by default, workflows cannot perform destructive actions or modify the repository [1][5]. You should then explicitly grant higher permissions only at the job level within individual workflow files [1][3][4]. 2. Securely Use pull_request_target The pull_request_target event is a high-risk trigger because it executes in the context of the base repository's default branch, granting access to secrets and potentially high-privilege tokens [6][7][8]. * Prefer the standard pull_request event, which is safer because it automatically restricts GITHUB_TOKEN permissions to read-only and withholds secrets when triggered from a fork [1][7][8]. * Never combine pull_request_target with a checkout of untrusted pull request code [7][8]. Doing so creates a pwn request vulnerability, where malicious code from a fork executes with the base repository's secrets [9][3][6]. * As of June 18, 2026, actions/checkout v7 automatically blocks the checkout of fork pull request code in pull_request_target and certain workflow_run workflows [9][3]. If you must check out untrusted code for specific, verified use cases, you must explicitly set allow-unsafe-pr-checkout: true [10][9][3]. Treat this as a significant security decision [9]. 3. Implement Fine-Grained Permissions Use the permissions key to restrict the GITHUB_TOKEN for every job [1][4]. * Start with an empty permissions block (permissions: {}) or read-all, then add only the specific scopes required [4]. * For checkout, typically only contents: read is needed [4]. * If you do not need the GITHUB_TOKEN at all, set permissions: {} to disable it entirely [4]. 4. General Hardening Best Practices * Use OIDC for cloud authentication instead of storing long-lived secrets [3][4]. * Pin actions to full commit SHAs to prevent supply-chain attacks via compromised action versions [4]. * Avoid using self-hosted runners on public repositories, as they are susceptible to compromise by any user who can open a pull request [2].

Citations:


Keep the deployment job read-only and disable checkout credential persistence.

pull-requests: write is job-scoped, so every step in deploy inherits PR write capability even though later steps only build/deploy. Move any PR commentary/commit-status actions to a separate job with pull-requests: write, keep the deploy job scoped to contents: read, and set persist-credentials: false for checkout to avoid later git commands reusing the token locally.

Proposed checkout hardening
       - name: Checkout
         uses: actions/checkout@v4
+
+          persist-credentials: false
🤖 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/landing-deploy.yml around lines 34 - 36, Update the deploy
job in the workflow to retain only contents: read permission, move any PR
commentary or commit-status steps into a separate job scoped with pull-requests:
write, and configure its checkout step with persist-credentials: false.

Source: Linters/SAST tools

Comment on lines +58 to +59
- name: Install Vercel CLI
run: npm install --global vercel@latest

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

printf '--- workflow snippet ---\n'
sed -n '45,70p' .github/workflows/landing-deploy.yml 2>/dev/null || true

printf '\n--- package manager/lock files (common names) ---\n'
git ls-files | grep -Ei '(^|/)(package-lock\.json|npm-shrinkwrap\.json|yarn\.lock|pnpm-lock\.yaml)$' || true

printf '\n--- Vercel CLI npm metadata for latest/dist-tags ---\n'
python3 - <<'PY'
import json, urllib.request
url='https://registry.npmjs.org/vercel'
with urllib.request.urlopen(url, timeout=20) as r:
    data=json.load(r)
print('current version:', data.get('dist-tags',{}).get('latest'))
print('dist-tags:', data.get('dist-tags'))
PY

printf '\n--- npm config relevant to global installs ---\n'
npm config get prefix 2>/dev/null || true
npm config get cache 2>/dev/null || true

Repository: juspay/neurolink

Length of output: 245


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- workflow snippet ---'
sed -n '45,70p' .github/workflows/landing-deploy.yml 2>/dev/null || true

echo
echo '--- package manager/lock files (common names) ---'
git ls-files | grep -Ei '(^|/)(package-lock\.json|npm-shrinkwrap\.json|yarn\.lock|pnpm-lock\.yaml)$' || true

echo
echo '--- Vercel CLI npm metadata for latest/dist-tags ---'
python3 - <<'PY'
import json, urllib.request
url='https://registry.npmjs.org/vercel'
with urllib.request.urlopen(url, timeout=20) as r:
    data=json.load(r)
print('current latest version:', data.get('dist-tags',{}).get('latest'))
print('dist-tags:', data.get('dist-tags'))
PY

echo
echo '--- npm config relevant to global installs ---'
npm config get prefix 2>/dev/null || true
npm config get cache 2>/dev/null || true

Repository: juspay/neurolink

Length of output: 3495


Pin the Vercel CLI used for deployments.

npm install --global vercel@latest installs the mutable latest registry tag on each fresh runner, separate from the repo’s checked-in pnpm-lock.yaml, so a newly published release can change deployment behavior without reviewing the workflow. Pin an exact validated version and update it explicitly.

Proposed fix
-          run: npm install --global vercel@latest
+          run: npm install --global vercel@<validated-version>
🧰 Tools
🪛 zizmor (1.28.0)

[warning] 59-59: ad-hoc installation of packages (adhoc-packages): installs a package outside of a lockfile

(adhoc-packages)

🤖 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/landing-deploy.yml around lines 58 - 59, Update the
“Install Vercel CLI” workflow step to install an exact validated Vercel CLI
version instead of the mutable latest tag, and retain that explicit version in
the command so future upgrades require a deliberate workflow change.

Source: Linters/SAST tools

Comment on lines +103 to +105
const existing = (
await github.rest.issues.listComments({ owner, repo, issue_number, per_page: 100 })
).data.find((c) => c.body && c.body.includes(marker));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow file excerpt =="
sed -n '1,160p' .github/workflows/landing-deploy.yml 2>/dev/null || true

echo
echo "== relevant GitHub Actions REST API usage =="
rg -n "issues.listComments|paginate|github-actions|preview|marker" .github/workflows/landing-deploy.yml .github/workflows 2>/dev/null || true

echo
echo "== package/workflow context =="
ls -la .github/workflows/landing-deploy.yml 2>/dev/null || true
git diff --stat HEAD~1..HEAD 2>/dev/null | sed -n '1,80p' || true

Repository: juspay/neurolink

Length of output: 7410


🌐 Web query:

GitHub REST API list issue comments per_page maximum 100

💡 Result:

The GitHub REST API enforces a maximum limit of 100 results per page for listing issue comments [1][2]. The default value for the per_page parameter is 30 [2][3]. It is important to note that if you provide a value for per_page that exceeds 100, the API will silently clamp the value to the maximum of 100 [4]. The request will still return a 200 OK status, meaning that if your application logic expects a higher number of results per page, it may under-fetch data without explicitly indicating that the limit was capped [4].

Citations:


🌐 Web query:

docs github actions github-script github.rest.issues.updateComment available actions rest API

💡 Result:

The github.rest.issues.updateComment method is available and is the standard way to update issue and pull request comments when using the actions/github-script action [1][2][3]. In the actions/github-script action, the github object provides a pre-authenticated Octokit client that includes the @octokit/plugin-rest-endpoint-methods plugin [1][4]. Starting with version 5 of actions/github-script, all REST API methods were moved under the github.rest namespace [1][5]. To use github.rest.issues.updateComment, you must provide the following required parameters [6][2]: owner: The owner of the repository. repo: The name of the repository. comment_id: The unique integer ID of the comment you wish to update. body: The new content of the comment (string). Below is a typical example of how this is used within an actions/github-script workflow step: await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: comment_id_variable, body: 'New comment body content' }); For comprehensive details on the parameters and behavior of this endpoint, you should refer to the official GitHub REST API documentation for "Update an issue comment" [6][7]. The github-script action itself relies on the underlying octokit/rest.js client, so you can also reference the octokit/plugin-rest-endpoint-methods documentation for further technical details [1][5].

Citations:


🌐 Web query:

Octokit paginate list issue comments maxPerPage 100

💡 Result:

When using Octokit to list issue comments, you can set per_page to 100 to optimize the number of requests made during pagination [1][2]. The per_page parameter defaults to 30, but the GitHub REST API supports a maximum of 100 per page [1][2]. You can use the octokit.paginate method in combination with the relevant REST endpoint method. Below is an example of how to fetch all issue comments for a specific issue using this configuration: const comments = await octokit.paginate(octokit.rest.issues.listComments, { owner: "OWNER", repo: "REPO", issue_number: 123, per_page: 100, }); In this example, octokit.paginate will automatically handle fetching subsequent pages until all results are retrieved [3][4]. The per_page: 100 setting ensures that each individual request retrieves the maximum number of items allowed, which helps minimize API overhead and reduce the likelihood of hitting rate limits [1][2].

Citations:


Make the sticky-comment lookup authoritative.

listComments is capped at 100 results per page, so PRs with more than 100 comments can get a new preview comment instead of updating the existing one. Also pin the lookup to the workflow bot author, since any comment containing the marker will currently be updated. Paginate the comments and require c.user?.login === 'github-actions[bot]' before updating.

🤖 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/landing-deploy.yml around lines 103 - 105, Update the
sticky-comment lookup around github.rest.issues.listComments to paginate through
all comment pages rather than limiting the search to one page, and only select a
comment whose c.user?.login equals github-actions[bot] in addition to containing
marker. Preserve the existing update-or-create flow using the authoritative
matching comment.

@Tara-ag

Tara-ag commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

APPROVED

This PR successfully migrates the landing site deployment from Vercel's Git integration to GitHub Actions, solving the persistent problem where fork PRs show red "requires authorization" status that camouflages real build failures.

Summary of Changes

File Added: .github/workflows/landing-deploy.yml (119 lines)

The new workflow:

  • Deploys to production when pushed to release branch with changes to landing/** or this workflow file
  • Deploys to preview for same-repo PRs touching landing/**, with a sticky PR comment containing the preview URL
  • Skips fork PRs entirely (no check appears), since GitHub withholds secrets from fork pull_request runs anyway

Verification Status

Workflow tested end-to-end: The preview deployment succeeded (comment ID 5122784624 shows working preview URL)
Secrets properly scoped: Uses repo-level secrets (VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID)
Follows existing patterns: Mirrors patterns in ci.yml (pnpm setup, Node.js v24, Vercel CLI installation)
No breaking changes: This is purely additive - existing Vercel Git integration remains unchanged until explicitly disconnected
Proper concurrency handling: Uses concurrency to cancel in-progress deployments
Path filtering: Only triggers on landing/** or workflow file changes

Why This Is Safe

  1. No security risks: Secrets are used via GitHub Actions' native secret injection (never exposed in code or logs)
  2. No API changes: This only affects CI/CD, not application behavior
  3. No breaking changes: Existing workflows continue to function; this is a parallel deployment mechanism
  4. Logic verified: The if: condition correctly filters to same-repo refs only, leveraging GitHub's built-in fork protection
  5. Well-documented: PR description clearly explains the problem, solution, and verification steps

Impact Assessment

  • Scope: CI/CD infrastructure only (.github/workflows/)
  • Risk level: Minimal (additive change following established patterns)
  • Dependencies: Requires pre-configured repo secrets (already exist per PR description)
  • Side effects: None beyond replacing the failed Vercel Git check with a skipped/no-op for forks

Recommendation

APPROVED — This change cleanly solves a persistent blocker for external contributions without introducing any risks. The workflow has been validated end-to-end with a successful preview deployment.


Reviewed by Yama on 2026-07-29

@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/landing-deploy.yml:
- Around line 40-48: Update the PR preview job in the workflow around the
same-repository condition and Vercel deployment steps to use a preview-scoped,
read-only Vercel token for pull request builds. Keep production-capable Vercel
credentials available only to the release-only job or protected environment, and
replace any PR-path references to secrets.VERCEL_TOKEN while preserving the
existing fork exclusion behavior.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5386a660-d9be-4351-972c-134ecf7ae829

📥 Commits

Reviewing files that changed from the base of the PR and between 993e1ff and 7d14f83.

📒 Files selected for processing (1)
  • .github/workflows/landing-deploy.yml

Comment on lines +40 to +48
# Same-repo refs only. Fork PRs skip → no check, rather than a red one.
if: >-
github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
timeout-minutes: 15
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

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 "== file exists and line count =="
if [ -f .github/workflows/landing-deploy.yml ]; then
  wc -l .github/workflows/landing-deploy.yml
else
  echo "missing .github/workflows/landing-deploy.yml"
  fd -a 'landing-deploy\.yml$' .
fi

echo "== relevant workflow contents =="
if [ -f .github/workflows/landing-deploy.yml ]; then
  nl -ba .github/workflows/landing-deploy.yml | sed -n '1,150p'
fi

echo "== workflow files containing VERCEL_TOKEN references =="
rg -n "VERCEL_(TOKEN|ORG_ID|PROJECT_ID)" .github/workflows || true

Repository: juspay/neurolink

Length of output: 302


🌐 Web query:

GitHub Actions pull requests from forks secrets security no-secrets documentation

💡 Result:

GitHub Actions security policy for pull requests originating from forks is designed to prevent unauthorized access to sensitive repository secrets [1][2][3]. By default, workflows triggered by the pull_request event for a pull request from a fork do not have access to secrets, and they are provided with a read-only GITHUB_TOKEN [4][1][2]. If a workflow requires access to secrets for a pull request from a fork, developers often use the pull_request_target event [5][4][6]. This event runs in the context of the base repository and does have access to secrets and a read/write GITHUB_TOKEN [5][4][2]. However, using this event introduces significant security risks because the workflow uses the repository's workflow file and is considered trusted, even though it is processing an untrusted pull request [5][7]. To securely handle these scenarios, follow these best practices: 1. Avoid checking out untrusted code: Never use actions/checkout to check out the head of an untrusted pull request in a workflow that has access to secrets [5][2][6]. Doing so allows the pull request's code (such as malicious build scripts or dependencies) to execute with the full privileges of the workflow, potentially leading to secret exfiltration [8][2][6]. 2. Use separate workflows: If you must test code from a fork and also perform actions requiring secrets, split the task into two workflows [6]. Use a pull_request event (without secrets) to test the untrusted code, and a separate pull_request_target event to perform the privileged operations, ensuring the latter never processes or executes the untrusted pull request code [2][6]. 3. Understand checkout protections: As of June 2026, actions/checkout (v7 and later) includes built-in protections that refuse to fetch code from a fork when used within pull_request_target workflows to prevent common "pwn request" vulnerabilities [8]. You should not override these protections (e.g., by setting allow-unsafe-pr-checkout: true) unless you have thoroughly audited the workflow to ensure that no untrusted code is executed [5][8]. 4. Configuration for private repositories: For private repositories, repository owners can adjust settings to enable or disable access to secrets and write tokens for pull requests from forks, but this should be done with extreme caution as it increases the risk of privilege escalation [9]. In summary, standard pull_request workflows are inherently safe from secret exfiltration because they lack access to them [2]. The use of pull_request_target is an intentional design choice for automation that requires elevated permissions, but it mandates strict separation between code execution and privileged secret handling to remain secure [5][2][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== relevant workflow contents =="
awk '{printf "%5d  %s\n", NR, $0}' .github/workflows/landing-deploy.yml | sed -n '1,140p'

echo
echo "== workflow files using Vercel tokens/secrets =="
rg -n "VERCEL_(TOKEN|ORG_ID|PROJECT_ID)|pull_request|pull_request_target|environment:" .github/workflows || true

echo
echo "== git diff stat/name/status =="
git diff --stat HEAD~1..HEAD 2>/dev/null || git diff --stat 2>/dev/null || true

Repository: juspay/neurolink

Length of output: 10010


🌐 Web query:

GitHub Actions pull_request same repository secrets access default security

💡 Result:

GitHub Actions handles secret access for pull requests differently depending on the source of the pull request and the specific trigger used [1][2][3]. For pull requests originating from a fork, GitHub enforces strict isolation for the pull_request event by default [1][2][3]: - Workflows triggered by pull_request for pull requests from forks do not have access to repository or organization secrets [1][4][3]. - They are also issued a read-only GITHUB_TOKEN to prevent unauthorized modifications to the repository [1][5][3]. For pull requests originating from the same repository (i.e., branches created directly within the base repository), workflows triggered by pull_request have access to repository secrets [2]. This is permitted because the user creating the pull request already possesses write access to the repository [2]. To handle scenarios requiring secret access for pull requests from forks, the pull_request_target trigger is available [1][2][6]. This trigger operates with elevated trust, granting access to secrets and a read/write GITHUB_TOKEN [1][7][3]. However, it is critical to note that pull_request_target executes the workflow file from the base repository's default branch rather than the pull request's branch [1][7]. While this provides a security boundary, it remains highly dangerous if the workflow subsequently checks out and runs code from the untrusted pull request branch [1][6][8]. If a workflow triggered by pull_request_target executes untrusted code, that code can compromise the repository and access the secrets available to the workflow [9][8][3]. In summary, the security model is designed to prevent secrets from leaking to untrusted fork code by withholding them from the standard pull_request event [2][3]. The pull_request_target trigger is a powerful tool for automation, but it must be used with extreme caution to ensure no untrusted input or code influences the execution of privileged steps [1][8][3].

Citations:


Use a preview-scoped Vercel token for PR builds.

This preview path now includes same-repository PRs and loads VERCEL_TOKEN, VERCEL_ORG_ID, and VERCEL_PROJECT_ID before running PR-controlled checkout/build commands. Forks are still excluded from secret-bearing runs, but not all same-repo PRs are equal; use a read-only preview deployment token for PRs and keep production-capable credentials behind a release-only job or protected environment. Also applies to the Vercel steps that use secrets.VERCEL_TOKEN.

🤖 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/landing-deploy.yml around lines 40 - 48, Update the PR
preview job in the workflow around the same-repository condition and Vercel
deployment steps to use a preview-scoped, read-only Vercel token for pull
request builds. Keep production-capable Vercel credentials available only to the
release-only job or protected environment, and replace any PR-path references to
secrets.VERCEL_TOKEN while preserving the existing fork exclusion behavior.

@murdore
murdore merged commit 48f832a into release Jul 30, 2026
18 checks passed
@murdore
murdore deleted the ci/landing-vercel-actions branch July 30, 2026 11:04
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 10.8.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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