Skip to content

ci: build base template via e2b CLI in addition to DockerHub push#1401

Open
mishushakov wants to merge 6 commits into
mainfrom
mishushakov/saskatoon-v1
Open

ci: build base template via e2b CLI in addition to DockerHub push#1401
mishushakov wants to merge 6 commits into
mainfrom
mishushakov/saskatoon-v1

Conversation

@mishushakov

@mishushakov mishushakov commented Jun 8, 2026

Copy link
Copy Markdown
Member

Adds a buildTemplate CI job that builds and publishes the base template through the e2b CLI, running alongside the existing DockerHub image push (renamed to buildAndPushImage). For security, the CLI is built from source in this repo rather than installing the published @e2b/cli package; this build-and-global-install logic lives in a reusable composite action at .github/actions/build-cli so it can be shared across workflows. Removes the static templates/base/e2b.toml since template config is now driven by the CLI invocation, and switches the Dockerfile's node user/group creation to system accounts (-r).

Usage

Any workflow can build and install the CLI globally with a single step:

steps:
  - uses: actions/checkout@v4
  - uses: ./.github/actions/build-cli
  - run: e2b template create base --memory-mb 512

🤖 Generated with Claude Code

Add a buildTemplate job that installs @e2b/cli from npm and runs
`e2b template create base --memory-mb 512`, alongside the existing
DockerHub image build. Drop the now-unused e2b.toml config.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 8, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: fbe6304

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@cursor

cursor Bot commented Jun 8, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
CI publishes templates with E2B_API_KEY, and removing pinned template metadata plus changing the image node user can affect template identity and sandbox file ownership.

Overview
Adds .github/actions/build-cli to install the CLI from packages/cli via pnpm and global npm install. templates.yml renames the Docker job to buildAndPushImage and adds buildTemplate, which uses E2B_API_KEY and runs e2b template create base --memory-mb 512 in templates/base. Deletes templates/base/e2b.toml. In e2b.Dockerfile, node is created as a system user/group instead of fixed UID/GID 1000.

The new CI step does not pass --dockerfile e2b.Dockerfile; it relies on the CLI default (e2b.Dockerfile first). Removing e2b.toml drops the committed template_id and team_id, so references to the old ID are no longer in-repo. The Dockerfile user change can alter UID/GID for node compared to the previous 1000:1000 setup.

Reviewed by Cursor Bugbot for commit fbe6304. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread .github/workflows/templates.yml Outdated
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Package Artifacts

Built from 248d6c5. Download artifacts from this workflow run.

JS SDK (e2b@2.28.3-mishushakov-saskatoon-v1.0):

npm install ./e2b-2.28.3-mishushakov-saskatoon-v1.0.tgz

CLI (@e2b/cli@2.11.1-mishushakov-saskatoon-v1.0):

npm install ./e2b-cli-2.11.1-mishushakov-saskatoon-v1.0.tgz

Python SDK (e2b==2.27.1+mishushakov-saskatoon-v1):

pip install ./e2b-2.27.1+mishushakov.saskatoon.v1-py3-none-any.whl

Comment thread .github/workflows/templates.yml Outdated

RUN groupadd --gid 1000 node \
&& useradd --uid 1000 --gid node --shell /bin/bash --create-home node
RUN groupadd -r node && useradd -r -g node -s /bin/bash -m node

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 The Dockerfile change from useradd --uid 1000 --gid 1000 to useradd -r (system account) is unrelated to this PR's CI scope and silently changes the runtime ABI of the published base template: node no longer has a stable, predictable UID/GID 1000 but instead gets a system UID allocated from /etc/login.defs's SYS_UID range (typically <1000), determined non-deterministically by whichever system accounts already exist in python:3.11.6. The line above still cites nodejs/docker-node as inspiration — that upstream pins UID 1000 by deliberate convention. Please either revert this change or restore explicit --uid 1000 --gid 1000 to preserve the contract for downstream consumers.

Extended reasoning...

What changes

-RUN groupadd --gid 1000 node \
-  && useradd --uid 1000 --gid node --shell /bin/bash --create-home node
+RUN groupadd -r node && useradd -r -g node -s /bin/bash -m node

The -r flag on useradd/groupadd requests a system account, which allocates a UID/GID from the system range bounded by SYS_UID_MIN/SYS_UID_MAX in /etc/login.defs (100–999 in Debian bookworm, the base of python:3.11.6). The previous code explicitly pinned the node user and group to UID/GID 1000.

Why this is a behavior change for the published template

This Dockerfile produces the base sandbox template that downstream users consume via Sandbox.create('base') and that template authors extend with their own Dockerfiles. The numeric identity of the node user is part of that template's surface area:

  1. The comment immediately above this line (# Inspired by https://github.com/nodejs/docker-node/blob/main/20/bookworm/Dockerfile) cites the canonical nodejs/docker-node Dockerfile, which deliberately pins node to UID 1000 to match the host-user convention. After this change, the cited convention no longer holds, and the comment is stale.
  2. The new UID is non-deterministic: it depends on which system users already exist in python:3.11.6 plus any system accounts created by the apt installs above (build-essential, util-linux, gh, …). A future bump of the python base image — or even a new transitive system user in any of those packages — can shift the node UID without any change to this Dockerfile.
  3. Downstream impact in derived images and at runtime:
    • COPY --chown=node:node (name-resolved) and COPY --chown=1000:1000 (numeric) now refer to different identities.
    • Bind-mounted host directories owned by UID 1000 — the host-user convention the previous code participated in — are no longer owned by node inside the sandbox.
    • Artifact consumers parsing UID/GID numerically see a different owner.

Step-by-step proof

Build the previous Dockerfile, then build the new one, in two scratch containers based on python:3.11.6:

# Old behavior
$ docker run --rm python:3.11.6 sh -c 'groupadd --gid 1000 node && useradd --uid 1000 --gid node --shell /bin/bash --create-home node && id node'
uid=1000(node) gid=1000(node) groups=1000(node)

# New behavior
$ docker run --rm python:3.11.6 sh -c 'groupadd -r node && useradd -r -g node -s /bin/bash -m node && id node'
uid=100(node) gid=101(node) groups=101(node)

The exact numeric UID/GID assigned in the second case is determined by useradd walking the system range looking for the first free slot — so the value drifts whenever the upstream image's system-user layout changes.

Addressing the refutation

A previous refutation argued that nothing in this repo currently does USER node or chown 1000, so the change is invisible. That reasoning is too narrow:

  • The base template is published (per the existing DockerHub push + the new e2b template create base step added in this same PR). Its consumers are not limited to this repository. They are arbitrary user-authored FROM base Dockerfiles and Sandbox.create('base') clients with bind-mounts. We cannot grep our own repo to assert no one depends on UID 1000.
  • The nodejs/docker-node Dockerfile likewise does not set USER node — that's exactly why it pins UID 1000: so downstream authors who do opt into USER node or numeric chowns get a stable identity. Removing the pin defeats that contract for our derived template too.
  • Even within this repo, the loss of a stable UID is a regression in determinism that's worth preserving regardless of current internal callers — system UID allocation is order-dependent and image-version dependent.

How to fix

Either:

  • Revert this hunk and leave the user-creation as it was (the cleanest option, since the PR's stated purpose is the CI changes), or
  • Keep the modernized flags but restore the pin: useradd --system --uid 1000 --gid node --shell /bin/bash --create-home node (and a matching groupadd --system --gid 1000 node).

If the intent is truly to switch to a system account, that should be its own PR with a changeset and a note that the published base template's UID has changed.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

user with uid 1000 and gid 1000 already exists

Build the CLI locally from the repo rather than installing the
published @e2b/cli package, so the template build runs trusted code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mishushakov mishushakov force-pushed the mishushakov/saskatoon-v1 branch from 0273ef7 to ee86f02 Compare June 8, 2026 10:22
Move the build-from-source + global install of the e2b CLI into a
reusable composite action at .github/actions/build-cli so it can be
shared across workflows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- name: Parse .tool-versions
uses: wistia/parse-tool-versions@v2.1.1
with:
filename: '.tool-versions'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Agentic Security Review
Severity: HIGH

This workflow executes wistia/parse-tool-versions@v2.1.1 by mutable tag inside a job that later uses E2B publishing credentials. Tag retarget or upstream compromise would allow attacker-controlled code to run in CI and steal those credentials.

Impact: A supply-chain compromise of the action can lead to unauthorized template publication/API usage via exfiltrated secrets.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit 7f29aeb. Configure here.


- name: Build and publish base template
working-directory: ./templates/base
run: e2b template create base --memory-mb 512

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Agentic Security Review
Severity: HIGH

E2B_API_KEY and E2B_ACCESS_TOKEN are defined at job scope, so every step in buildTemplate (including checkout and CLI build/install steps) receives publishing credentials. This broadens the blast radius of any compromised action/dependency script before publish executes.

Impact: CI supply-chain compromise in an earlier step can exfiltrate template-publishing credentials and enable unauthorized template publication/API actions.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit 7f29aeb. Configure here.

mishushakov and others added 2 commits June 8, 2026 20:23
The CLI no longer gates `template create` on an access token, so the
E2B_API_KEY is sufficient.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d7a7776. Configure here.

Comment thread .github/workflows/templates.yml
link-workspace-packages is disabled, so the CLI resolves its `e2b`
dependency from the published registry package (which ships a prebuilt
dist) rather than the workspace source. Building packages/js-sdk first
had no effect on the CLI build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant