Using private GitHub repositories with Vercel Sandbox

Learn how to use Vercel Sandbox with private GitHub repositories using fine-grained tokens, classic tokens, or GitHub App tokens.

3 min read
Last updated February 13, 2026

When using Vercel Sandbox with private repositories, you need to authenticate with a GitHub personal access token or Github App token. This guide explains how.

  • A Vercel account
  • The @vercel/sandbox SDK installed
  • Access to a private GitHub repository

The Sandbox.create() method initializes the environment with the provided repository and configuration options, including authentication credentials, timeout, and exposed ports. Once created, you can execute commands inside the sandboxed environment using runCommand.

import { Sandbox } from '@vercel/sandbox';
import ms from 'ms';
async function main() {
const sandbox = await Sandbox.create({
source: {
url: 'https://github.com/your-org/private-repo.git',
type: 'git',
username: 'x-access-token',
password: process.env.GIT_ACCESS_TOKEN!,
},
timeout: ms('5m'),
ports: [3000],
});
const result = await sandbox.runCommand('echo', ['Hello sandbox!']);
console.log(`Message: ${await result.stdout()}`);
}
main().catch(console.error);

GitHub offers several authentication methods. Choose the one that best fits your use case.

Fine-grained tokens offer repository-specific access and enhanced security. This is the recommended approach for individual developers.

  1. Go to GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
  2. Click Generate new token
  3. Configure the token:
  • Token name: Give it a descriptive name (e.g., "Vercel Sandbox Access")
  • Expiration: Set an appropriate expiration date
  • Resource owner: Select your account or organization
  • Repository access: Choose "Selected repositories" and select your private repo
  • Repository permissions: Grant Contents: Read and Metadata: Read
  1. Click Generate token and copy the token

For platforms where users install your GitHub App, use installation access tokens. This is the recommended approach for multi-tenant platforms.

GitHub App tokens provide several advantages:

  • Short-lived tokens (1 hour) reduce security risk
  • Users grant access through GitHub's familiar OAuth flow
  • Tokens are scoped to specific installations
  • Higher rate limits than personal access tokens

Generate an installation token using the GitHub API:

import { App } from '@octokit/app';
import { Sandbox } from '@vercel/sandbox';
const app = new App({
appId: process.env.GITHUB_APP_ID!,
privateKey: process.env.GITHUB_APP_PRIVATE_KEY!,
});
async function createSandboxForUser(installationId: number, repoUrl: string) {
// Generate a short-lived installation token
const octokit = await app.getInstallationOctokit(installationId);
const { token } = await octokit.rest.apps.createInstallationAccessToken({
installation_id: installationId,
});
const sandbox = await Sandbox.create({
source: {
url: repoUrl,
type: 'git',
username: 'x-access-token',
password: token,
},
timeout: 5 * 60 * 1000,
ports: [3000],
});
return sandbox;
}

Classic tokens work similarly to fine-grained tokens but with broader scope. Create one at GitHub Settings → Developer settings → Personal access tokens → Tokens (classic) with the repo scope.

When building a platform where users bring their own private repositories, follow this pattern:

  1. Create a GitHub App and configure it with the Contents: Read permission
  2. Users install your app on their repositories through GitHub's OAuth flow
  3. Store the installation ID when the user completes the installation
  4. Generate a fresh token each time you create a sandbox
  5. Pass the token to Sandbox.create() as shown above

After creating the sandbox, run commands to install dependencies and start your application:

const sandbox = await Sandbox.create({
source: {
url: 'https://github.com/your-org/private-repo.git',
type: 'git',
username: 'x-access-token',
password: token,
},
timeout: 5 * 60 * 1000,
ports: [3000],
});
// Install dependencies
const install = await sandbox.runCommand({
cmd: 'npm',
args: ['install'],
stdout: process.stdout,
stderr: process.stderr,
});
if (install.exitCode !== 0) {
throw new Error('Installation failed');
}
// Start the dev server in the background
await sandbox.runCommand({
cmd: 'npm',
args: ['run', 'dev'],
detached: true,
});
// Get the sandbox URL
console.log(`Sandbox running at: ${sandbox.domain(3000)}`);
  • Never log or store tokens in plain text
  • Use environment variables to pass tokens to your application
  • Prefer short-lived tokens (GitHub App installation tokens) over long-lived personal access tokens
  • Grant minimal permissions Read is sufficient for cloning
  • Rotate tokens regularly if using personal access tokens

Was this helpful?

supported.