Vercel Container Registry public repositories: safely sharing Sandbox images across teams

HAGO··schedule23분
공유

Vercel Container Registry (VCR) gained public repositories on August 7, 2026. "Public" has a narrower meaning here than it does in casual Docker conversation. Vercel says anyone with a Vercel account, or any Vercel team, can pull and use an image. It does not say anonymous clients on the open internet can pull without authentication. Public access is also read-only: consumers cannot push, delete, or change repository settings.

That sounds simple until a public image becomes part of a deployment pipeline. Repository visibility, image identity, and Sandbox execution are separate controls. Opening read access does not make an image trustworthy. Keeping access private does not make a mutable :latest tag reproducible. Treating either control as a substitute for the other is where teams get surprised.

This article uses the August 7 announcement, the public and shared repository documentation, and the Sandbox image documentation, checked on August 9, 2026. VCR is marked Beta in the current docs. The examples target @vercel/sandbox 3.0.0 and Vercel CLI 58.9.0, the versions returned by npm during this review. I did not run them against a live Vercel account.

What changed, and what did not

VCR already allowed a repository owner to share read access with named Vercel teams. The documented limit is 100 teams per repository. Public visibility replaces that allowlist with read access for every Vercel team. A repository remains private by default.

You can change visibility in the project dashboard under Images, select the repository, open Settings, and confirm Public Access by entering the repository name. The documented CLI commands are:

# Command form documented for Vercel CLI 58.9.0
vercel vcr config my-repository --public true

# Return the repository to private visibility
vercel vcr config my-repository --public false

The switch applies to the whole repository, including every image and tag. It is not a per-tag publishing control. If one repository contains a stable runtime image, internal debugging tools, and half-finished experimental tags, all of them enter the readable set when the repository becomes public. Split public artifacts into a dedicated repository before flipping the switch.

The confirmed permission boundary

Public and explicitly shared consumers can pull images and use them in Vercel Sandbox. They cannot push images, delete images, alter the repository, or pass their granted share to another team. Those limits are documented behavior.

Read-only does not mean harmless. A consumer can inspect image layers and execute their contents. A token copied into a layer during a careless build is still exposed, even though nobody else can push. Do not bake .env files, credentials, or production configuration into an image. Supply secrets through a runtime mechanism with its own access policy.

Public is not documented as anonymous

The announcement says "anyone with a Vercel account" while the detailed guide says "any Vercel team." Both descriptions include an identity boundary. They do not establish anonymous Docker Registry pulls as a supported contract. Automation should record which Vercel team authenticates the pull rather than assuming that public visibility removes authentication.

If anonymous distribution is a requirement, test it explicitly with a clean client that has no Vercel credentials. A successful pull from a developer laptop may only prove that the developer was already authenticated.

Draw the boundaries before changing visibility

A VCR image used by Sandbox crosses several owners and permission systems:

Developer or CI job
  -> Dockerfile / Containerfile
  -> local or CI image builder
  -> authenticated push with source-project write permission
  -> VCR repository owned by one Vercel project
  -> public/shared/private read decision
  -> authenticated consumer team
  -> Sandbox.create({ image })
  -> microVM filesystem
  -> application process started with runCommand()

VCR repositories belong to projects. The docs say that even another project in the same team needs the repository shared with that team. A bare image name resolves against the authenticated project. Images owned elsewhere use a team-scoped reference such as team/project/repository:tag or the digest form.

Public visibility changes the repository read decision. It does not grant application authorization inside the consumer's project, configure Sandbox networking, or validate the program in the image. These are different boundaries with different failure modes.

Locate failures at the right boundary

A not_found error can point to the team, project, repository, tag, digest, or visibility setting. A command failure after Sandbox is ready points inside the image or application. A network error may belong to the Sandbox firewall or destination service. These are not one generic registry failure.

The current Sandbox guide requires linux/amd64 custom images and says Docker ENTRYPOINT and CMD are ignored. Start the process with sandbox.runCommand(). Visibility does not change either constraint.

Pin the digest, not only the tag

The announcement uses :latest because it makes a short example. In production, a tag can be moved to a different manifest while keeping the same name. A consumer that needs repeatable environments should pass team/project/repository@sha256:.... The Sandbox docs explicitly support tag and digest references.

A digest proves content identity, not safety. It prevents the selected bytes from changing under the same reference. It does not prove who built those bytes, whether dependencies are vulnerable, or whether secrets were copied into a layer. Provenance, scanning, approval, and retirement still need their own checks.

Add a consumer-side regression probe

The following TypeScript probe rejects mutable references, creates a Sandbox from an approved digest, and checks both the runtime major and a marker written into the image at build time. It is application code rather than an installation-only snippet. It has not been executed in this environment because no live Vercel project was used.

import assert from 'node:assert/strict';
import { Sandbox } from '@vercel/sandbox';

const image = process.env.VCR_IMAGE_DIGEST;
assert.match(
  image ?? '',
  /^[a-z0-9-]+\/[a-z0-9-]+\/[a-z0-9._-]+@sha256:[a-f0-9]{64}$/,
  'Use a team/project/repository digest reference',
);

const sandbox = await Sandbox.create({ image: image! });

try {
  const probe = await sandbox.runCommand(
    'sh',
    '-lc',
    'node --version && cat /opt/image-version',
  );
  const stdout = await probe.stdout();
  const stderr = await probe.stderr();

  assert.equal(probe.exitCode, 0, stderr);
  assert.match(stdout, /^v24\./m);
  assert.ok(stdout.includes(process.env.EXPECTED_IMAGE_MARKER ?? ''));
} finally {
  await sandbox.stop();
}

The regex is deliberately strict and may need adjusting if your valid Vercel slugs use a broader character set. The useful rule is not the exact regex; it is refusing an unpinned tag in the production path. Keep the approved digest in deployment configuration, not in user input.

Installing @vercel/sandbox 3.0.0 does not validate account permissions or image compatibility. It only makes the documented API available to the client process. Check the SDK reference again before a major upgrade, especially the Sandbox.create() options and command result interface.

Use a staged release sequence

Build and scan the image first. Push a version tag and capture the resulting digest. Run the probe from the intended consumer project while the repository is privately shared. Make the repository public only after the digest passes. Finally, repeat the pull and Sandbox test as a different team, since the new capability is the cross-team read path.

Returning a repository to private visibility blocks future reads; it cannot recall layers that consumers already pulled. If an image ever contained a secret, rotate the secret. Changing the visibility toggle is access control, not data erasure.

Do not invent a performance win

The announcement does not publish pull latency, boot latency, or a speed comparison between public and named-team sharing. There is no basis here for claiming that public repositories make Sandbox faster. The image docs say custom images can contain packages and toolchains so that nothing needs to be installed at runtime. That is an architecture property, not a measured end-to-end improvement for a specific workload.

Image size, layer caching, region, first pull, platform preparation, and the command itself can all affect latency. One stopwatch around the full request cannot identify which stage changed.

Record stage markers that you can actually observe

Record create_requested, sandbox_ready, probe_started, probe_first_output, probe_completed, and sandbox_stopped. Run a clearly separated first trial and at least ten repeated trials with the same digest. Preserve the digest, SDK version, CLI version, region, command, exit code, and output marker with every sample.

Compare the custom image with a Vercel managed image and, if relevant, the previous runtime-install workflow. Report p50 and p95 for first and repeated runs, plus failure rate and error categories. Do not call the Sandbox.create() interval "download time" unless Vercel exposes a download-only timer. That interval may include reference resolution, authorization, image preparation, and microVM startup.

Output equivalence matters too. A smaller image that boots sooner but omits a required binary is not an optimization. The version and marker probe gives the comparison a basic correctness guard; a real application should add its own smoke request or regression test.

Claim audit and safer wording

Confirmed: VCR repositories are private by default. Public visibility allows every Vercel team to read all images and tags in the repository, without push or delete rights.

Conditionally true: "Anyone can use the image" is accurate only within the documented Vercel account and team context. Safer wording: "Any authenticated Vercel team can pull the public repository."

Confirmed: Visibility applies to the repository, not one chosen tag. Review every layer and tag before publishing.

Conditionally true: A custom image can remove runtime installation steps. Whether it reduces readiness time for your workload requires first-run and repeated measurements.

Unverified: Public visibility is faster than sharing with named teams. Neither the current announcement nor this review establishes that result.

Overstated: "Read-only means secure" ignores exposed layers and execution risk. Read-only access limits repository mutation; it does not validate or sanitize image content.

Public repositories are useful when more than 100 teams need the same base image or when an organization wants a broadly reusable Sandbox environment. Private or named-team sharing remains the sensible default for internal images. When public access is justified, isolate the repository, pin a digest, test from another team, and keep the execution policy separate from the visibility setting. The toggle is easy. The trust decision still belongs to the consumer.

Official references

공유

댓글 (0)

첫 댓글을 남겨주세요.