@mastra/e2b 0.12.2 → 0.12.3-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { MastraSandbox, ProcessHandle, SandboxNotReadyError, SandboxProcessManager, UnsupportedStdinCloseError, assertModesUnsupported } from "@mastra/core/workspace";
2
2
  import { Sandbox, Template } from "e2b";
3
- import { createHash, randomBytes } from "crypto";
3
+ import { createHash } from "crypto";
4
4
  import { execFile } from "child_process";
5
5
  import { promisify } from "util";
6
6
  import { FRAME_PREFIX, buildProgramModule, buildRunner, sanitizeToolId } from "@mastra/core/tools";
@@ -161,16 +161,42 @@ Error details: ${installResult.stderr || installResult.stdout}`);
161
161
  const hasSecretKey = !!config.secretAccessKey;
162
162
  if (hasAccessKey !== hasSecretKey) throw new Error("Both accessKeyId and secretAccessKey must be provided together.");
163
163
  const hasCredentials = hasAccessKey && hasSecretKey;
164
+ if (config.sessionToken && !hasCredentials) throw new Error("sessionToken requires accessKeyId and secretAccessKey.");
165
+ const useSessionToken = hasCredentials && !!config.sessionToken;
164
166
  const credentialsPath = `/tmp/.passwd-s3fs-${createHash("md5").update(mountPath).digest("hex").slice(0, 8)}`;
165
167
  if (!hasCredentials && config.endpoint) throw new Error(`S3-compatible storage requires credentials. Detected endpoint: ${config.endpoint}. The public_bucket option only works for AWS S3 public buckets, not R2, MinIO, etc.`);
168
+ let bucketArg = config.bucket;
169
+ if (config.prefix) {
170
+ const normalizedPrefix = validatePrefix(config.prefix);
171
+ bucketArg = `${config.bucket}:/${normalizedPrefix}`;
172
+ }
173
+ const removeSessionCredentials = async () => {
174
+ try {
175
+ await sandbox.commands.run(`sudo rm -f ${credentialsPath}`);
176
+ } catch {
177
+ logger.warn(`${LOG_PREFIX} Failed to remove S3 session credentials file`);
178
+ }
179
+ };
166
180
  if (hasCredentials) {
167
- const credentialsContent = `${config.accessKeyId}:${config.secretAccessKey}`;
181
+ const credentialsContent = useSessionToken ? [
182
+ `export AWSACCESSKEYID=${shellQuote$1(config.accessKeyId)}`,
183
+ `export AWSSECRETACCESSKEY=${shellQuote$1(config.secretAccessKey)}`,
184
+ `export AWSSESSIONTOKEN=${shellQuote$1(config.sessionToken)}`,
185
+ `export AWS_ACCESS_KEY_ID=${shellQuote$1(config.accessKeyId)}`,
186
+ `export AWS_SECRET_ACCESS_KEY=${shellQuote$1(config.secretAccessKey)}`,
187
+ `export AWS_SESSION_TOKEN=${shellQuote$1(config.sessionToken)}`
188
+ ].join("\n") : `${config.accessKeyId}:${config.secretAccessKey}`;
168
189
  await sandbox.commands.run(`sudo rm -f ${credentialsPath}`);
169
- await sandbox.files.write(credentialsPath, credentialsContent);
170
- await sandbox.commands.run(`chmod 600 ${credentialsPath}`);
190
+ try {
191
+ await sandbox.files.write(credentialsPath, credentialsContent);
192
+ await sandbox.commands.run(`chmod 600 ${credentialsPath}`);
193
+ } catch (error) {
194
+ if (useSessionToken) await removeSessionCredentials();
195
+ throw error;
196
+ }
171
197
  }
172
198
  const mountOptions = [];
173
- if (hasCredentials) mountOptions.push(`passwd_file=${credentialsPath}`);
199
+ if (hasCredentials) mountOptions.push(useSessionToken ? "use_session_token" : `passwd_file=${credentialsPath}`);
174
200
  else {
175
201
  mountOptions.push("public_bucket=1");
176
202
  logger.debug(`${LOG_PREFIX} No credentials provided, mounting as public bucket (read-only)`);
@@ -186,12 +212,8 @@ Error details: ${installResult.stderr || installResult.stdout}`);
186
212
  mountOptions.push("ro");
187
213
  logger.debug(`${LOG_PREFIX} Mounting as read-only`);
188
214
  }
189
- let bucketArg = config.bucket;
190
- if (config.prefix) {
191
- const normalizedPrefix = validatePrefix(config.prefix);
192
- bucketArg = `${config.bucket}:/${normalizedPrefix}`;
193
- }
194
- const mountCmd = `sudo s3fs ${shellQuote$1(bucketArg)} ${shellQuote$1(mountPath)} -o ${mountOptions.join(" -o ")}`;
215
+ const s3fsCmd = `s3fs ${shellQuote$1(bucketArg)} ${shellQuote$1(mountPath)} -o ${mountOptions.join(" -o ")}`;
216
+ const mountCmd = useSessionToken ? `sudo sh -c ${shellQuote$1(`. ${credentialsPath} && exec ${s3fsCmd}`)}` : `sudo ${s3fsCmd}`;
195
217
  logger.debug(`${LOG_PREFIX} Mounting S3:`, hasCredentials ? mountCmd.replace(credentialsPath, "***") : mountCmd);
196
218
  try {
197
219
  const result = await sandbox.commands.run(mountCmd, { timeoutMs: 6e4 });
@@ -211,6 +233,8 @@ Error details: ${installResult.stderr || installResult.stdout}`);
211
233
  error: String(error)
212
234
  });
213
235
  throw new Error(`Failed to mount S3 bucket: ${stderr || stdout || error}`);
236
+ } finally {
237
+ if (useSessionToken) await removeSessionCredentials();
214
238
  }
215
239
  if ((await sandbox.commands.run(`mountpoint -q ${shellQuote$1(mountPath)}`)).exitCode !== 0) throw new Error(`s3fs returned exit 0 but ${mountPath} is not a mountpoint. The s3fs daemon likely failed during FUSE init (common causes: region mismatch, invalid credentials, or an S3-compatible endpoint that rejects the signature). Re-run inside the sandbox with '-f -o dbglevel=info' to see the underlying error.`);
216
240
  }
@@ -2053,7 +2077,7 @@ var E2BCodeModeTransport = class {
2053
2077
  externalName: sanitizeToolId(toolId)
2054
2078
  }));
2055
2079
  const allowList = new Set(toolIds);
2056
- const suffix = randomBytes(4).toString("hex");
2080
+ const suffix = Buffer.from(globalThis.crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(4))).toString("hex");
2057
2081
  const dir = `${SANDBOX_TMP}/${suffix}`;
2058
2082
  const programPath = `${dir}/program-${suffix}.mjs`;
2059
2083
  const runnerPath = `${dir}/runner-${suffix}.mjs`;