Implements the `lifecycle` prop on `Sandbox.create`, taking over and
deprecating the `beta_pause` functionality.
Currently supports:
- `on_timeout`: `kill` (default) | `pause`. Controls what should happen
to the sandbox when it hits end of life. Pause allows for resuming
- `auto_resume`: False (default) | True. Whether the sandbox should
autoresume on traffic
Intended for additional functionality as we update the backend to
support additional props. Blocked from deploying until the API and
client-proxy are deployed but for pre-approval.
(Meant to be extended later as add more capabilities to the API)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes the API contract and request payload shape for sandbox
auto-resume and alters lifecycle/timeout behavior mapping, which could
break older integrations if backend/client versions are mismatched.
>
> **Overview**
> Adds a new `lifecycle` configuration on `Sandbox.create` (JS + Python)
to control what happens at timeout (`kill` vs `pause`) and whether
paused sandboxes auto-resume on traffic (`auto_resume`).
>
> Deprecates `betaPause`/`beta_pause` and the JS `autoPause` create
option in favor of the new lifecycle semantics, updates connect/pause
call paths accordingly, and expands tests to cover resume-on-connect and
auto-resume behaviors.
>
> Updates the OpenAPI contract and generated clients so `autoResume` is
now an object with an `enabled: boolean` flag (removing the previous
policy enum), and bumps SDK versions via a changeset.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
515f9b7fc13a5ec13db75450e8f6252e3c7bcf03. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- Add `GET /templates/{templateID}/tags` endpoint to the OpenAPI spec
- Add `Template.getTags()` to JS/TS SDK
- Add `Template.get_tags()` (sync) and `AsyncTemplate.get_tags()`
(async) to Python SDK
- Returns a list of `TemplateTag` objects with `tag`, `buildId`, and
`createdAt` fields
## Test plan
- Added unit tests for JS SDK (`Template.getTags` happy path + 404
error)
- Added unit tests for Python SDK (sync + async, happy path + error)
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Clarifies connection behavior in JS SDK API clients; no functional
changes.
>
> - Adds inline comments in `api/index.ts` and `envd/api.ts` noting that
undici keeps connections alive by default and leaves `keepalive`
commented out
> - No code path, config, or runtime behavior modified
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
127f6fe57151e86a0a5280af58902f1efb1e46ee. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Medium Risk**
> Primarily dependency/lockfile updates across the JS monorepo; risk
comes from transitive runtime changes and potential build/lint behavior
shifts after the version bumps.
>
> **Overview**
> Updates JS dependencies across the repo and refreshes the
`pnpm-lock.yaml` to match.
>
> Also bumps tooling-related versions (notably `pnpm` via
`packageManager` and the ESLint/TypeScript ESLint toolchain) and
adds/keeps a `pnpm.overrides` pin for `@next/eslint-plugin-next`'s
`glob` dependency.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
eceea9624f031c7d3ba74000018f01c71cfc510e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Low Risk**
> Low risk dependency-only change; behavior should be unchanged aside
from upstream `tar` bugfixes/patches that could subtly affect archive
creation in the JS SDK.
>
> **Overview**
> Updates the JS SDK dependency on `tar` from `^7.5.4` to `^7.5.9` in
`packages/js-sdk/package.json`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
664f95865263fe5f42b60bc3516240bb89fb879e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
The infra now validates sandbox ID format (^[a-z0-9]+$), allowing only
lowercase alphanumeric characters. The test was using
'non-existing-sandbox' which fails format validation due to hyphens,
returning a 400 error instead of reaching the expected 404 path.
This updates the test to use 'nonexistingsandbox' — a valid format that
doesn't exist, so it properly hits the 404 "not found" response and
returns false as expected.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: test-only change that updates hardcoded IDs to match new
validation rules, without modifying runtime logic.
>
> **Overview**
> Updates JS and Python SDK `kill non-existing sandbox` tests to use a
lowercase alphanumeric sandbox ID (`nonexistingsandbox`) instead of a
hyphenated one, so the tests exercise the intended *not-found* path
rather than failing format validation.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e43acb66ef4465ae60a368ac8c7377023b4a6da3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Jakub Novak <jakub@e2b.dev>
The Yarn GPG key (6A010C5166006599AA17F08146C2130DFD2497F5) can no
longer be fetched from keyservers, it returns "no user ID". So the
signature verification fails. So let's just download yarn via npm and
simplify this.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Build-only change confined to the Dockerfile; main risk is potential
reproducibility/supply-chain differences from switching Yarn
installation method.
>
> **Overview**
> Updates `templates/base/e2b.Dockerfile` to install Yarn via `npm
install -g yarn@1.22.19` instead of downloading and GPG-verifying the
Yarn tarball, removing the keyserver dependency and associated
verification steps.
>
> Also normalizes the Node version env var syntax from `ENV NODE_VERSION
20.9.0` to `ENV NODE_VERSION=20.9.0`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
243ce4b47da851e3faf64e2329016ef7a9681632. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
the logs test on the cli can just be really slow and time out resulting
in false positives; will want to establish faster --limit at some point
maybe.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Test-only changes that reduce coverage for `sandbox logs` but do not
affect production logic.
>
> **Overview**
> Disables the `sandbox logs` backend integration test in
`backend_integration.test.ts` by commenting it out with a note about
slow log availability causing timeouts.
>
> Minor formatting fix in `runCliWithPipedStdin` to correct indentation
around the constructed `ETIMEDOUT` error object.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
bbc4720e3f253d55eb583de50ab42cd71248b135. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- Skip the unnecessary `isRunning()` API call and `wait(400)` when
`--follow` is not set in `sandbox logs`, preventing flaky timeouts in
the backend integration test
- Fix `waitForSandboxEnd` to return the `running` variable instead of
the `isRunning` function reference, so the follow-mode loop actually
terminates when the sandbox stops
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Small control-flow fixes in the CLI logs loop and sandbox status
monitor; low blast radius with minimal behavioral change beyond making
termination conditions correct.
>
> **Overview**
> `sandbox logs` now breaks out immediately after printing the first
batch when `--follow` isn’t set, avoiding extra status polling/sleeps
that could cause flaky timeouts.
>
> Fixes `waitForSandboxEnd` to return the mutable `running` boolean
(instead of the `isRunning` function reference), so follow-mode loops
can actually stop when the sandbox exits.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
87cd7af5b1bdf9a7a4fe16e7a2100256b3d55d7b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Example:
```
e2b sbx create base -d
```
Output:
```
Use the following link to inspect this Sandbox live inside the E2B Dashboard️:
↪ https://e2b.dev/dashboard/inspect/sandbox/i4dct03zur3guplje3eia
Sandbox created with ID i4dct03zur3guplje3eia using template base
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Small CLI behavior change isolated to sandbox creation/connection
flow; primary risk is unintended behavior differences in terminal-attach
path due to the refactor.
>
> **Overview**
> Adds `-d, --detach` to `e2b sandbox create` so users can create a
sandbox and get its dashboard/ID output without connecting a terminal.
>
> Refactors sandbox creation to happen in the command handler and passes
the created `sandbox` into `connectSandbox`, which now only manages the
keep-alive loop and terminal attachment when not detached.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cb8be14bb71073b8299010cd45509ca2a58ca32e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This PR updates the sandbox spawn process to print the inspect URL to
the console when a new sandbox is created using `e2b sbx spawn` or `e2b
sbx create`. This makes it easier for users to access and debug new
sandboxes directly after creation.
<img width="556" height="87" alt="Screenshot 2025-09-15 at 2 54 22 PM"
src="https://github.com/user-attachments/assets/783129e3-443d-4a7c-a86e-a4265d90831f"
/>
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: primarily adds extra CLI output and URL construction with
env-configurable base; no changes to sandbox lifecycle or auth logic.
>
> **Overview**
> **Prints a Dashboard inspection link when connecting to or creating a
sandbox.** Both `sandbox connect` and `sandbox create` now output a
terminal-clickable E2B Dashboard *Inspect Sandbox* URL immediately after
obtaining the `sandboxId`.
>
> Adds `DASHBOARD_BASE`/`SANDBOX_INSPECT_URL` (env-overridable via
`E2B_DASHBOARD_BASE`/`E2B_DOMAIN`) and a new
`printDashboardSandboxInspectUrl` helper to format and print the link,
plus a changeset bump for `@e2b/cli`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f132029f7540408e47e4c37ee58716c95c63a000. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Low Risk**
> Mostly CI/test changes plus a small logging tweak; low production
impact, with main risk being altered test timing/flake behavior due to
new timeout defaults.
>
> **Overview**
> Improves release-candidate GitHub workflows by passing sanitized
`tag`/`preid` via step `env` vars and quoting them when running `npm
version`/`npm publish`, reducing the chance of input/expansion issues.
>
> Stabilizes sandbox internet-access tests in JS and Python by switching
the curl target to Google’s `generate_204` endpoint and updating
expected status codes. Python tests also tighten global `pytest` timeout
to 30s, remove per-sandbox default timeouts from fixtures, and add 180s
timeouts specifically for template test suites via new `conftest.py`
files.
>
> CLI sandbox status polling now logs the caught error when
`Sandbox.getInfo` fails (instead of silently returning `false`).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
187849338dd46f9d0dd1adb0a070719ebad87309. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Low Risk**
> Documentation-only change with no runtime or behavioral impact.
>
> **Overview**
> Adds `CLAUDE.md` with contributor workflow notes: preferred dependency
managers (pnpm/poetry), required formatting/lint/typecheck steps, how to
run tests, how to regenerate the API client (`make codegen`), and where
default credentials are stored.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b1c2f5a07871b7577f806f45ce3a52829b40fdd0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Potential fix for
[https://github.com/e2b-dev/E2B/security/code-scanning/3](https://github.com/e2b-dev/E2B/security/code-scanning/3)
In general, the fix is to declare an explicit `permissions` block that
restricts the `GITHUB_TOKEN` to the minimal scope required. For this
workflow, the steps only need to read the repository contents to check
out code and run tooling; they do not perform any write operations
against the GitHub API, so `contents: read` at the workflow or job level
is sufficient.
The best minimal fix is to add a top-level `permissions` block
immediately after the `name: Lint` line in `.github/workflows/lint.yml`.
This will apply to all jobs in the workflow (currently just `lint`)
without altering any existing steps. The block should be:
```yaml
permissions:
contents: read
```
No additional imports, steps, or changes to the existing job logic are
required.
_Suggested fixes powered by Copilot Autofix. Review carefully before
merging._
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> CI-only change that narrows GitHub token permissions; no application
logic or deployment behavior is affected.
>
> **Overview**
> Adds an explicit top-level `permissions` block to the `Lint` GitHub
Actions workflow, restricting the default `GITHUB_TOKEN` to
**read-only** repository access (`contents: read`).
>
> No lint job steps or behavior are changed; the update is purely to
tighten workflow token scope to satisfy code-scanning guidance.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fd6bd36e778825fcf2f1c9d758c65b36ba0a045a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Potential fix for
[https://github.com/e2b-dev/E2B/security/code-scanning/4](https://github.com/e2b-dev/E2B/security/code-scanning/4)
In general, the fix is to explicitly declare a `permissions:` block that
grants only the minimal required scopes. Since this workflow only needs
to read repository contents (to check out code and inspect git
status/diff) and does not perform any writes via the GitHub API,
`contents: read` is sufficient.
The best minimally invasive fix is to add a `permissions:` block at the
workflow root (top level, alongside `on:` and `jobs:`) so that it
applies to all jobs in this workflow. Concretely, in
`.github/workflows/generated_files.yml`, insert:
```yaml
permissions:
contents: read
```
between the `on:` block (lines 3–5) and the `jobs:` block (line 6). No
changes to steps, images, or other configuration are required, and no
additional imports or tools are needed. This documents the workflow’s
needs and prevents it from gaining unintended write powers if repository
defaults change.
_Suggested fixes powered by Copilot Autofix. Review carefully before
merging._
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Workflow-only change that restricts token permissions; no application
logic or data paths are affected.
>
> **Overview**
> Tightens the GitHub Actions `Generated files` workflow by explicitly
setting top-level `permissions` to `contents: read`.
>
> This addresses code-scanning guidance by ensuring the workflow token
is read-only while still allowing `actions/checkout` and the
generated-file checks to run.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
225a3ee2370629605e4372768b3d018031e68e9e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Low Risk**
> Only build tooling/dependency metadata changes; no runtime or product
code paths are modified.
>
> **Overview**
> Removes the `update-deps` script and `npm-check-updates` dev
dependency from both `packages/cli` and `packages/js-sdk`.
>
> Updates `pnpm-lock.yaml` to drop `npm-check-updates` and its
transitive dependency set, reducing lockfile size and dependency surface
area.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
61529b6b5303ce1a5ecafa1e3adb65fea4facae2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Update broken downloads badge
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Documentation-only change that updates external badge image URLs and
styling; no runtime or build behavior is affected.
>
> **Overview**
> Fixes broken download badges in `README.md` and
`packages/python-sdk/README.md`.
>
> The PyPI badge is switched from shields.io to a Pepy monthly downloads
badge, and the NPM badge label/styling is updated to explicitly show
*monthly* downloads.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
811324dd583dd068f6a763489ac6c63483c47f87. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- Resolved 43 type diagnostics reported by ty (Astral's Python type
checker)
- Fixed Self type issues on class singletons
- Added explicit type annotations for shadowed attributes
- Replaced None with UNSET for auto-generated API parameters
- Fixed method signature alignment for protocol matching
- Added targeted type: ignore suppressions for pattern-based limitations
All checks pass: ty check, ruff format, ruff check.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Mostly typing/CI changes, but some adjustments affect sandbox
connect/pause overload dispatch and API response/parameter handling
(`UNSET` vs `None`), which could alter edge-case runtime behavior.
>
> **Overview**
> Fixes Python SDK static typing issues for Astral’s `ty` checker and
wires typechecking into CI.
>
> Adds a new `Typecheck` GitHub Action plus workspace `typecheck`
scripts (TS packages via `tsc`, Python SDK via `make typecheck` running
`ty`), and publishes a patch changeset for `@e2b/python-sdk`.
>
> Across the Python SDK, adjusts type annotations and overloads (e.g.,
`Self`/singleton typing, `connect` overloads, optional
`user`/token/domain handling), tightens API model parsing with
`cast`/`Optional` checks and `UNSET` usage, and adds a few targeted `ty`
ignore comments in tests/protocols to silence checker limitations.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f66402847c40cee7e44e1aaa7caa97e271ba9978. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
## Summary
- Fixes `ty` type checker reporting `error[no-matching-overload]` when
calling `Sandbox.kill()` (and all other methods using the
`class_method_variant` pattern)
- Single 2-line change: make `class_method_variant` inherit from
`Generic[T]` instead of `object`
## Problem
The `class_method_variant` descriptor uses `cast(T, self)` to tell type
checkers that the decorator preserves the original function's type.
Without `Generic[T]`, `T` is only a method-level TypeVar — `ty` doesn't
trust the cast and fails to resolve overloads at call sites. `mypy` and
`pyright` are more lenient and accept it either way.
Affected methods (both `Sandbox` and `AsyncSandbox`): `kill`, `connect`,
`set_timeout`, `get_info`, `get_metrics`, `beta_pause`.
## Fix
Adding `Generic[T]` makes `T` a class-level type parameter, so `ty` can
track the type binding through the descriptor
(`class_method_variant[(self, **opts) -> bool]`). The cast then makes
sense to all three type checkers.
## Verification
Tested with a consumer repro (`sandbox.kill()`) against:
| Type Checker | Before | After |
|---|---|---|
| ty 0.0.15 | `error[no-matching-overload]` | All checks passed |
| mypy 1.19.1 | All checks passed | All checks passed |
| pyright 1.1.408 | All checks passed | All checks passed |
## Test plan
- [x] Verified `ty check` passes on consumer-side repro
- [x] Verified `mypy` and `pyright` still pass (no regressions)
- [x] Verified Python syntax is valid
- [x] No runtime behavior change (`Generic[T]` only affects type-level
metadata)
Summary
- When E2B_API_KEY is set via environment variable, the CLI no longer
falls back to the teamId from
~/.e2b/config.json, avoiding "Team ID param mismatch with the API key"
errors
- Adds E2B_TEAM_ID environment variable support
- Introduces resolveTeamId() helper with clear precedence: --team CLI
flag > E2B_TEAM_ID env var > config
file (only when E2B_API_KEY env var is not set)
Problem
When using E2B_API_KEY env var (e.g. for local development or CI with a
different team), the CLI still
reads teamId from ~/.e2b/config.json and sends it as a query parameter.
If the config file belongs to a
different team than the API key, the API rejects the request with 400:
Team ID param mismatch with the
API key.
Changes
- api.ts: Export E2B_TEAM_ID env var, add resolveTeamId() helper
- list.ts, build.ts, delete.ts, publish.ts: Use resolveTeamId() instead
of inline userConfig?.teamId
fallback
Test plan
- Set E2B_API_KEY to a key from team A, have ~/.e2b/config.json with
team B's ID → e2b template list
should work (no mismatch error)
- Set both E2B_API_KEY and E2B_TEAM_ID → CLI uses the env var team ID
- Without any env vars, normal e2b auth login flow still works as before
- --team flag still takes highest priority
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Small, localized change to CLI argument/env/config precedence for team
selection; main risk is behavior changes for users relying on implicit
`~/.e2b/config.json` teamId when also setting `E2B_API_KEY`.
>
> **Overview**
> Fixes sandbox template commands failing with "Team ID param mismatch"
when `E2B_API_KEY` is set via environment by changing team resolution
precedence and avoiding `~/.e2b/config.json` team fallback in that case.
>
> Introduces `E2B_TEAM_ID` and a centralized `resolveTeamId()` helper
(CLI flag > env var > local `e2b.toml` > user config *only when no env
API key*), and updates template `build`, `list`, `delete`, and `publish`
flows to use it consistently. Adds a changeset bump for `@e2b/cli`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
905172fc8e59f8325a8d36af913326f7eb47a15f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add path validation to the copy method in both JS and Python SDKs to
ensure source paths are always relative and don't escape the context
directory.
This prevents:
- Absolute paths like /absolute/whatever (Unix) or C:\whatever (Windows)
- Path traversal attacks like ../whatever or ./foo/../../../bar
The validation works cross-platform using Node's
path.isAbsolute/normalize and Python's os.path.isabs/normpath plus
PureWindowsPath for detecting Windows paths on Unix.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes behavior of `copy`/`copy_items` to throw earlier for
previously-accepted absolute or escaping paths, which could break some
consumers; logic is localized and well-covered by tests.
>
> **Overview**
> Prevents path traversal in template `copy` operations by validating
`src` is *relative* and does not escape the context directory (rejects
absolute paths and `..`-based escapes) in both the JS and Python SDKs.
>
> Updates `copyItems`/`copy_items` error handling to preserve the
caller’s stack trace when validation fails, adds unit coverage for the
new path validator plus new stack-trace tests for absolute-path
failures, and ships as patch releases via a changeset.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c1a8eb978e3fd99fa829d571e811bb7ee18cd40b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Fixes issue with missing `restore` and `reset` functionality on the
async git sandboxes.
Consolidate shared git helpers by moving remote URL argument
construction and
parsing into the git utilities package. Sync and async git modules now
reuse
the same builders where possible, with tests to ensure no drift.
---------
Co-authored-by: Filip Brebera <filip@bxxf.dev>