agenticmail 0.5.32 → 0.5.34

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/cli.js CHANGED
@@ -4235,6 +4235,10 @@ function fail2(msg) {
4235
4235
  function info2(msg) {
4236
4236
  console.log(` ${c2.dim(msg)}`);
4237
4237
  }
4238
+ function maskSecret(secret) {
4239
+ if (secret.length <= 12) return "****";
4240
+ return secret.slice(0, 4) + "\u2026" + secret.slice(-4);
4241
+ }
4238
4242
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
4239
4243
  var LOADING_MESSAGES = {
4240
4244
  docker: [
@@ -4510,12 +4514,15 @@ async function startApiServer(config) {
4510
4514
  }
4511
4515
  async function killProcessOnPort(port) {
4512
4516
  try {
4513
- const { execSync } = await import("child_process");
4514
- const pids = execSync(`lsof -ti :${port}`, { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim().split("\n").filter(Boolean);
4517
+ const { execFileSync } = await import("child_process");
4518
+ const pids = execFileSync("lsof", ["-ti", `:${port}`], { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).toString().trim().split("\n").filter(Boolean);
4515
4519
  for (const pid of pids) {
4516
- try {
4517
- process.kill(parseInt(pid, 10), "SIGTERM");
4518
- } catch {
4520
+ const n = parseInt(pid, 10);
4521
+ if (!isNaN(n) && n > 0) {
4522
+ try {
4523
+ process.kill(n, "SIGTERM");
4524
+ } catch {
4525
+ }
4519
4526
  }
4520
4527
  }
4521
4528
  } catch {
@@ -4821,7 +4828,7 @@ async function cmdSetup() {
4821
4828
  log2("");
4822
4829
  info2("You can set up email later by running: " + c2.green("npx agenticmail setup"));
4823
4830
  log2("");
4824
- log2(` ${c2.dim("Your secret key:")} ${c2.yellow(result.config.masterKey)}`);
4831
+ log2(` ${c2.dim("Your secret key:")} ${c2.yellow(maskSecret(result.config.masterKey))}`);
4825
4832
  log2(` ${c2.dim("Settings saved:")} ${c2.cyan(result.configPath)}`);
4826
4833
  log2("");
4827
4834
  process.exit(0);
@@ -4975,7 +4982,7 @@ function printSummary(result, exitAfter) {
4975
4982
  log2("");
4976
4983
  log2(` Here are your details (save these somewhere safe):`);
4977
4984
  log2("");
4978
- log2(` ${c2.dim("Your secret key:")} ${c2.yellow(result.config.masterKey)}`);
4985
+ log2(` ${c2.dim("Your secret key:")} ${c2.yellow(maskSecret(result.config.masterKey))}`);
4979
4986
  log2(` ${c2.dim("Settings saved:")} ${c2.cyan(result.configPath)}`);
4980
4987
  log2(` ${c2.dim("Server address:")} ${c2.cyan(`http://${result.config.api.host}:${result.config.api.port}`)}`);
4981
4988
  log2("");
@@ -5211,7 +5218,7 @@ async function setupRelay(config, previous) {
5211
5218
  log2("");
5212
5219
  ok2(`Your AI agent ${c2.bold('"' + data.agent.name + '"')} is ready!`);
5213
5220
  log2(` ${c2.dim("Agent email:")} ${c2.cyan(data.agent.subAddress)}`);
5214
- log2(` ${c2.dim("Agent key:")} ${c2.yellow(data.agent.apiKey)}`);
5221
+ log2(` ${c2.dim("Agent key:")} ${c2.yellow(maskSecret(data.agent.apiKey))}`);
5215
5222
  log2("");
5216
5223
  info2("People can email your agent at the address above.");
5217
5224
  await sendWelcomeEmail(apiBase, data.agent.apiKey, relayInfo.email, data.agent.name, data.agent.subAddress);
@@ -6173,9 +6180,9 @@ async function cmdOpenClaw() {
6173
6180
  log2(` ${c2.dim("Agent:")} ${c2.bold(agentName)} (${c2.cyan(agentEmail)})`);
6174
6181
  }
6175
6182
  if (agentApiKey) {
6176
- log2(` ${c2.dim("API Key:")} ${c2.yellow(agentApiKey)}`);
6183
+ log2(` ${c2.dim("API Key:")} ${c2.yellow(maskSecret(agentApiKey))}`);
6177
6184
  }
6178
- log2(` ${c2.dim("Master Key:")} ${c2.yellow(config.masterKey)}`);
6185
+ log2(` ${c2.dim("Master Key:")} ${c2.yellow(maskSecret(config.masterKey))}`);
6179
6186
  log2(` ${c2.dim("Server:")} ${c2.cyan(apiBase)}`);
6180
6187
  let smsPhone = "";
6181
6188
  if (agentApiKey) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agenticmail",
3
- "version": "0.5.32",
3
+ "version": "0.5.34",
4
4
  "description": "Email and SMS infrastructure for AI agents \u2014 the first platform to give agents real email addresses and phone numbers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { execSync, execFileSync } from 'node:child_process';
13
- import { readFileSync, writeFileSync, existsSync, rmSync, unlinkSync } from 'node:fs';
13
+ import { readFileSync, writeFileSync, existsSync, rmSync, unlinkSync, lstatSync, realpathSync } from 'node:fs';
14
14
  import { join } from 'node:path';
15
15
  import { homedir, platform } from 'node:os';
16
16
 
@@ -91,8 +91,22 @@ if (existsSync(openclawConfig)) {
91
91
 
92
92
  const dataDir = join(home, '.agenticmail');
93
93
  if (existsSync(dataDir)) {
94
- log('Removing ~/.agenticmail/ ...');
95
- try { rmSync(dataDir, { recursive: true, force: true }); } catch { /* ignore */ }
94
+ // Safety: verify it's not a symlink pointing outside home (symlink attack prevention)
95
+ try {
96
+ const stat = lstatSync(dataDir);
97
+ if (stat.isSymbolicLink()) {
98
+ const realPath = realpathSync(dataDir);
99
+ if (!realPath.startsWith(home)) {
100
+ log(`WARNING: ~/.agenticmail is a symlink to ${realPath} (outside home dir) — skipping removal`);
101
+ } else {
102
+ log('Removing ~/.agenticmail/ (symlink) ...');
103
+ try { rmSync(dataDir, { recursive: true, force: true }); } catch { /* ignore */ }
104
+ }
105
+ } else {
106
+ log('Removing ~/.agenticmail/ ...');
107
+ try { rmSync(dataDir, { recursive: true, force: true }); } catch { /* ignore */ }
108
+ }
109
+ } catch { /* stat failed — skip */ }
96
110
  }
97
111
 
98
112
  log('Uninstall complete.');