Skip to content

Update dependency e2b to v2.46.0 - #254

Closed
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/e2b-2.x-lockfile
Closed

Update dependency e2b to v2.46.0#254
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/e2b-2.x-lockfile

Conversation

@renovate

@renovate renovate Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
e2b (source) 2.39.12.46.0 age confidence

Release Notes

e2b-dev/e2b (e2b)

v2.46.0

Minor Changes
  • 9d1c90d: Remove client-side API key format validation. The SDK no longer checks that the API key matches the e2b_ hex format — only that a key is present. The validateApiKey/validate_api_key option is deprecated and has no effect, and the E2B_VALIDATE_API_KEY environment variable is no longer read. The server remains the source of truth for key validity.
Patch Changes
  • 67c06e0: Point the two Code Interpreter README links at code-interpreting/analyze-data-with-ai instead of the code-interpreting section index. The index has no landing page and 307s to that article, dropping the query string on the way, so the UTM parameters were lost before the reader arrived. Linking at the resolved path keeps them.

  • 182b498: Point the README documentation links at docs.e2b.dev instead of e2b.dev/docs. The docs site moved to its own subdomain and has no /docs path prefix there, so e2b.dev/docs serves a 308 to docs.e2b.dev/ and e2b.dev/docs/code-interpreting maps to docs.e2b.dev/code-interpreting. The UTM parameters are unchanged and survived the redirect, so this removes a redirect hop rather than fixing broken attribution.

  • b802997: Fix two network.egressProxy / network["egress_proxy"] cases an untyped caller reaches.

    The JS SDK had no shape guard: buildEgressProxyBody rebuilds the body from the known fields, so an address that was missing or not a string vanished and the caller got an API error about a config they never wrote ({"egressProxy":{}}). It now raises InvalidArgumentError naming the option, the way the Python SDK already did:

    // InvalidArgumentError: network egressProxy must be an object with a string
    // 'address' (e.g. 'proxy.example.com:1080').
    await Sandbox.create({
      network: { egressProxy: 'proxy.example.com:1080' as never },
    })

    A null / None username or password is now treated as absent instead of being serialized as a JSON null the API rejects — reading a credential out of an unset environment variable is how a caller lands there, and it means the proxy takes no credentials:

    await Sandbox.create({
      network: {
        egressProxy: {
          address: 'proxy.example.com:1080',
          // Unset in the environment; the proxy takes no credentials.
          username: process.env.PROXY_USER,
        },
      },
    })
    Sandbox.create(
        network={
            "egress_proxy": {
                "address": "proxy.example.com:1080",
                "username": os.environ.get("PROXY_USER"),
            },
        },
    )

v2.45.1

Patch Changes
  • b17b726: Stop the shared retrying transports from mirroring streamed request bodies in
    memory. pyqwest's retry middleware keeps a non-bytes body replayable by
    copying it as it is sent, so a streamed files.write of a file-like object or
    volume.write_file grew a full in-RAM mirror and peak memory scaled with file
    size. The transports now declare pyqwest's RetryMode.UNBUFFERED: a streamed
    body is replayed only while nothing has been read from it, which is all the
    SDK's connect-only retry policy needs — a ConnectionError is raised only
    before the request was written. Connect retries are unchanged, and bytes
    bodies (unary RPC payloads, in-memory writes) were already replayable without
    a copy.

v2.45.0

Compare Source

Minor Changes
  • 8787dfe: Add sorting and new filters to Sandbox.list. The order option ('asc' / 'desc', default 'desc') sorts sandboxes by start time across the whole paginated dataset, and the query now supports startedAfter / started_after (inclusive lower bound on start time) and template (exact template ID or alias) filters, all applied server-side before pagination. The CLI e2b sandbox list command exposes these via --order, --started-after, and --template.

v2.44.0

Compare Source

Minor Changes
  • 5759f17: Add an E2B client that binds a connection config once and exposes the resource surfaces off it, so a single process can talk to several API keys, domains or deployments. The classes it exposes are per-client subclasses of the real Sandbox/Volume/Template/Secret classes, so they behave exactly like the top-level ones — per-call options still win over the client's options, which win over the environment variables. The named top-level exports are unchanged and keep reading the environment.

    Nothing existing changes: Template is now the TemplateBase class made callable as a factory, so Template(...), the statics and instanceof keep working, and the default export is still Sandbox.

    import { E2B } from 'e2b'
    
    const { Sandbox, Volume, Template, Secret } = new E2B({
      apiKey: 'e2b_***',
      domain: 'e2b.dev',
    })
    
    const sandbox = await Sandbox.create()
    const volume = await Volume.create('my-volume')
    const exists = await Template.exists('my-template')
    await Template.build(Template().fromPythonImage('3'), 'my-env')
    await Secret.create('openai-api-key', 'sk-***')
    from e2b import E2B
    
    client = E2B(api_key="e2b_***", domain="e2b.dev")
    Sandbox, Volume, Template = client.Sandbox, client.Volume, client.Template
    Secret = client.Secret
    
    sandbox = Sandbox.create()
    volume = Volume.create("my-volume")
    exists = Template.exists("my-template")
    secret = Secret.create("openai-api-key", "sk-***")
    
    # Async variants are exposed too.
    AsyncSandbox = client.AsyncSandbox
    async_sandbox = await AsyncSandbox.create()

v2.43.0

Compare Source

Minor Changes
  • f89f8c3: Add Secrets Management to the SDK. The Secret class (and AsyncSecret in Python) now manages E2B secrets: create and update store secret values (write-only — no read surface returns them), getInfo / get_info and the paginated list read metadata, exists and destroy are idempotent existence and lifecycle helpers, and fill formats the ${e2b.secrets.name} placeholder that the runtime resolves to the secret's current value.
Patch Changes
  • 2be6c12: Internal refactor: the template API operations resolve their connection config through a class-level hook, so a TemplateBase subclass can carry bound connection options. No behavior change — Template / AsyncTemplate keep reading config from per-call options and environment variables. In the Python SDK the terminal template operations (build, build_in_background, get_build_status, exists, alias_exists, assign_tags, remove_tags, get_tags) became classmethods, with signatures unchanged for callers.
  • 05aa03c: Add typed not-found errors for volumes: VolumeNotFoundError / VolumeNotFoundException (thrown when a volume is not found) and VolumePathNotFoundError / VolumePathNotFoundException (thrown when a path inside a volume is not found). All subclass the existing NotFoundError / NotFoundException, so existing catches keep working.

v2.42.0

Compare Source

Minor Changes
  • 7af41e9: Refresh the MCP server types from the current MCP gateway catalog: 49 servers are new (n8n, neo4j, okta, temporal, proxmox, zscaler, the AWS Labs family, ...), 61 titles and 10 descriptions were rewritten, and 4 servers changed their options (awsDiagram, context7, neo4jCypher, onlyofficeDocspace).

    Six servers the catalog no longer publishes are gone from McpServer: postgres, root, tembo, flexprice, triplewhale, cdataConnectcloud. awsDiagram and context7 now require an option (outputDir and apiKey), so awsDiagram: {} and context7: {} stop type-checking, and onlyofficeDocspace is down to baseUrl and docspaceApiKey. The removals also narrow McpServerName, so Template().addMcpServer('postgres') stops compiling. The config is still passed to the gateway as written, so a dropped server can be kept by casting past the type — whether it starts is up to the gateway.

    import { Sandbox } from 'e2b'
    
    const sandbox = await Sandbox.create({
      mcp: {
        n8n: {
          apiKey: process.env.N8N_API_KEY!,
          apiUrl: 'https://n8n.example.com/api/v1',
        },
      },
    })
Patch Changes
  • 15bd48b: Omit autoPause from the create-sandbox request when no timeout lifecycle is configured, and omit autoPauseMemory unless keepMemory / keep_memory was chosen. Sending the SDK's local defaults for those fields was indistinguishable from an explicit choice, so the API could not tell "no preference" from a client choice and own its defaults. Explicit values are still always sent:

    import { Sandbox } from 'e2b'
    
    // No timeout lifecycle: autoPause is omitted, the API applies its default.
    await Sandbox.create()
    
    // Explicit action: autoPause: false / autoPause: true, as before.
    await Sandbox.create({ lifecycle: { onTimeout: 'kill' } })
    await Sandbox.create({ lifecycle: { onTimeout: 'pause' } })
    
    // Snapshot kind is only sent when keepMemory is set.
    await Sandbox.create({
      lifecycle: { onTimeout: { action: 'pause', keepMemory: false } },
    })
    from e2b import Sandbox
    
    # No timeout lifecycle: auto_pause is omitted, the API applies its default.
    Sandbox.create()
    
    # Explicit action: autoPause: false / autoPause: true, as before.
    Sandbox.create(lifecycle={"on_timeout": "kill"})
    Sandbox.create(lifecycle={"on_timeout": "pause"})
    
    # Snapshot kind is only sent when keep_memory is set.
    Sandbox.create(
        lifecycle={"on_timeout": {"action": "pause", "keep_memory": False}}
    )
  • 5367693: Omit autoResume from the POST /sandboxes request when lifecycle.autoResume / lifecycle["auto_resume"] is not configured, instead of sending the SDK's local default as { "autoResume": { "enabled": false } }. The API can now tell an unset preference from an explicit opt-out and own the default itself. Explicit values are unchanged on the wire.

    import { Sandbox } from 'e2b'
    
    // autoResume is left out of the request entirely — the API's default applies
    await Sandbox.create({ lifecycle: { onTimeout: 'pause' } })
    
    // an explicit choice is still sent as before
    await Sandbox.create({ lifecycle: { onTimeout: 'pause', autoResume: true } })
    from e2b import Sandbox
    
    # auto_resume is left out of the request entirely — the API's default applies
    Sandbox.create(lifecycle={"on_timeout": "pause"})
    
    # an explicit choice is still sent as before
    Sandbox.create(lifecycle={"on_timeout": "pause", "auto_resume": True})
  • 666241d: Run every persistent HTTP stack in the SDK on one shared pyqwest connection pool
    instead of four: the control-plane REST API, the envd HTTP API, the envd RPC
    clients, and the volume content API now all draw from
    e2b.api.client_sync/client_async, keyed on the three knobs that are fixed
    when a pyqwest transport is built — proxy, idle read bound, and HTTP version.
    reqwest pools per host internally, so one pool serves the API host and every
    per-sandbox host without interference — and since envd RPC and the envd HTTP API
    hit the same host, an active sandbox now needs a single HTTP/2 connection instead
    of one per stack. Streamed downloads keep a pool of their own, the only one
    carrying the idle read_timeout: reqwest's read timer runs during body send and
    TTFB, so on a shared pool it would cut off long uploads. No signature changes —
    get_transport and get_envd_transport keep the http2 parameter restored in
    2.39.1, and the two are now the same pool per key rather than two.

  • 2daced6: Tag the package homepage and README links with UTM parameters (utm_source=npm/pypi) so registry traffic to e2b.dev is attributed correctly. No functional change.

v2.41.0

Compare Source

Minor Changes
  • 6824cdf: Add network.egressProxy / network["egress_proxy"] for routing a sandbox's outbound TCP through a SOCKS5 proxy you operate ("bring your own proxy"). Tunneling happens on the host after the allowOut / denyOut lists are evaluated, so nothing runs inside the sandbox and code running there can neither see the proxy nor route around it. UDP-based traffic — DNS and QUIC/HTTP3 — is not tunneled.

    import { Sandbox } from 'e2b'
    
    const sandbox = await Sandbox.create({
      network: {
        egressProxy: {
          address: 'proxy.example.com:1080',
          username: 'proxy-user',
          password: 'proxy-password',
        },
      },
    })
    from e2b import Sandbox
    
    sandbox = Sandbox.create(
        network={
            "egress_proxy": {
                "address": "proxy.example.com:1080",
                "username": "proxy-user",
                "password": "proxy-password",
            },
        },
    )

    It combines with the rest of the network configuration — here everything except api.example.com is denied, and the traffic that is allowed goes through your proxy:

    await Sandbox.create({
      network: {
        allowOut: ['api.example.com'],
        denyOut: ({ allTraffic }) => [allTraffic],
        egressProxy: { address: 'proxy.example.com:1080' },
      },
    })
    Sandbox.create(
        network={
            "allow_out": ["api.example.com"],
            "deny_out": lambda ctx: [ctx.all_traffic],
            "egress_proxy": {"address": "proxy.example.com:1080"},
        },
    )

    updateNetwork / update_network sets or replaces the proxy on a sandbox that is already running, with no restart. The update replaces the whole configuration instead of merging into it, so an update that leaves the proxy out stops tunneling — repeat it in every update that should keep it.

    // Start tunneling on the running sandbox
    await sandbox.updateNetwork({
      allowOut: ['api.example.com'],
      denyOut: ({ allTraffic }) => [allTraffic],
      egressProxy: { address: 'proxy.example.com:1080' },
    })
    
    // Stop tunneling: an update without egressProxy clears it
    await sandbox.updateNetwork({})
    # Start tunneling on the running sandbox
    sandbox.update_network({
        "allow_out": ["api.example.com"],
        "deny_out": lambda ctx: [ctx.all_traffic],
        "egress_proxy": {"address": "proxy.example.com:1080"},
    })
    
    # Stop tunneling: an update without egress_proxy clears it
    sandbox.update_network({})

    getInfo / get_info reports the proxy the sandbox's egress is currently tunneled through. The password is never returned, so the returned SandboxEgressProxyInfo does not have the field at all:

    const info = await sandbox.getInfo()
    console.log(info.network?.egressProxy)
    // { address: 'proxy.example.com:1080', username: 'proxy-user' }
    info = sandbox.get_info()
    print((info.network or {}).get("egress_proxy"))
    # {'address': 'proxy.example.com:1080', 'username': 'proxy-user'}

    Egress fails closed: when the proxy is unreachable or does not speak SOCKS5, outbound connections fail rather than falling back to a direct connection. The address is validated server-side when the sandbox is created — a rejected create leaves nothing behind. Available on E2B Cloud and in BYOC deployments; a sandbox that names a proxy on a deployment built from the open source e2b-dev/infra repository is rejected as unsupported.

Patch Changes
  • 02ba746: Raise the h2 floor to >=4.4.1 so it can no longer resolve to a version affected by CVE-2026-71554, where a duplicate Host header is forwarded to the consuming application and becomes a request smuggling primitive once HTTP/2 is downgraded to HTTP/1.1.

  • e2eebd5: Fix URL encoding of namespaced template names and aliases in the Python SDK.

    The endpoints that take a template ID also accept a template name, and names may
    be namespaced (e.g. namespace/name). The SDK interpolated them into the request
    path without encoding, so a call like Template.exists("namespace/name") hit
    /templates/aliases/namespace/name instead of
    /templates/aliases/namespace%2Fname — the slash split the route rather than
    staying inside one path segment. Every method that takes a template ID or name,
    an alias, or a snapshot ID in the path — Template.exists / alias_exists,
    get_tags, the build/upload/status calls, and Sandbox.delete_snapshot (whose
    snapshot IDs are namespace/name:tag) — now percent-encodes the value, matching
    the JavaScript SDK (which already encodes path parameters via
    encodeURIComponent).

    from e2b import Template, Sandbox
    
    # Namespaced templates now resolve correctly
    Template.exists("my-team/my-template")
    Template.get_tags("my-team/my-template")
    
    # Namespaced snapshots can now be deleted
    Sandbox.delete_snapshot("my-team/my-snapshot:default")

v2.40.0

Minor Changes
  • 6248b12: Remove the deprecated accessToken / access_token option and its E2B_ACCESS_TOKEN environment fallback. E2B access tokens are no longer accepted for API authentication, so the SDKs no longer resolve one or send it as an Authorization: Bearer header — requests authenticate with the API key alone.

    If you were relying on the option to send a bearer token to a custom deployment, pass the header directly, which is what the deprecation notice already pointed to:

    // Before
    const sandbox = await Sandbox.create({ accessToken: token })
    
    // After
    const sandbox = await Sandbox.create({
      apiHeaders: { Authorization: `Bearer ${token}` },
    })
    # Before
    config = ConnectionConfig(access_token=token)
    
    # After
    config = ConnectionConfig(api_headers={"Authorization": f"Bearer {token}"})

    Note that Sandbox.envd_access_token / traffic_access_token are unrelated per-sandbox tokens and are unaffected.


Configuration

📅 Schedule: (in timezone UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
renovate Bot requested a review from mishushakov as a code owner August 26, 2026 14:37
@cla-bot cla-bot Bot added the cla-signed label Aug 26, 2026
@renovate

renovate Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Renovate Ignore Notification

Because you closed this PR without merging, Renovate will ignore this update (^2.20.3). You will get a PR once a newer version is released. To ignore this dependency forever, add it to the ignoreDeps array of your Renovate config.

If you accidentally closed this PR, or if you changed your mind: rename this PR to get a fresh replacement PR.

@renovate
renovate Bot deleted the renovate/e2b-2.x-lockfile branch August 26, 2026 14:52
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