@spinabot/brigade 1.19.0 → 1.19.2

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.
Files changed (58) hide show
  1. package/README.md +12 -7
  2. package/dist/agents/channels/bluebubbles/media.d.ts.map +1 -1
  3. package/dist/agents/channels/bluebubbles/media.js +5 -1
  4. package/dist/agents/channels/bluebubbles/media.js.map +1 -1
  5. package/dist/agents/channels/channel-messaging-registry.d.ts.map +1 -1
  6. package/dist/agents/channels/channel-messaging-registry.js +4 -2
  7. package/dist/agents/channels/channel-messaging-registry.js.map +1 -1
  8. package/dist/agents/channels/slack/format.d.ts.map +1 -1
  9. package/dist/agents/channels/slack/format.js +4 -2
  10. package/dist/agents/channels/slack/format.js.map +1 -1
  11. package/dist/agents/channels/telegram/format.d.ts.map +1 -1
  12. package/dist/agents/channels/telegram/format.js +7 -4
  13. package/dist/agents/channels/telegram/format.js.map +1 -1
  14. package/dist/agents/channels/telegram/media.d.ts.map +1 -1
  15. package/dist/agents/channels/telegram/media.js +31 -1
  16. package/dist/agents/channels/telegram/media.js.map +1 -1
  17. package/dist/agents/channels/whatsapp/connection.d.ts.map +1 -1
  18. package/dist/agents/channels/whatsapp/connection.js +59 -5
  19. package/dist/agents/channels/whatsapp/connection.js.map +1 -1
  20. package/dist/agents/extensions/modules/duckduckgo.d.ts.map +1 -1
  21. package/dist/agents/extensions/modules/duckduckgo.js +13 -1
  22. package/dist/agents/extensions/modules/duckduckgo.js.map +1 -1
  23. package/dist/agents/extensions/modules/wikipedia.d.ts.map +1 -1
  24. package/dist/agents/extensions/modules/wikipedia.js +16 -8
  25. package/dist/agents/extensions/modules/wikipedia.js.map +1 -1
  26. package/dist/agents/memory/graph.js +2 -2
  27. package/dist/agents/memory/graph.js.map +1 -1
  28. package/dist/agents/memory/records.d.ts.map +1 -1
  29. package/dist/agents/memory/records.js +6 -1
  30. package/dist/agents/memory/records.js.map +1 -1
  31. package/dist/agents/routing/account-id.d.ts.map +1 -1
  32. package/dist/agents/routing/account-id.js +17 -7
  33. package/dist/agents/routing/account-id.js.map +1 -1
  34. package/dist/agents/routing/session-key.d.ts.map +1 -1
  35. package/dist/agents/routing/session-key.js +15 -7
  36. package/dist/agents/routing/session-key.js.map +1 -1
  37. package/dist/agents/skills/install.d.ts.map +1 -1
  38. package/dist/agents/skills/install.js +11 -2
  39. package/dist/agents/skills/install.js.map +1 -1
  40. package/dist/agents/tools/ooxml-images.d.ts.map +1 -1
  41. package/dist/agents/tools/ooxml-images.js +5 -2
  42. package/dist/agents/tools/ooxml-images.js.map +1 -1
  43. package/dist/agents/tools/web-fetch-utils.d.ts.map +1 -1
  44. package/dist/agents/tools/web-fetch-utils.js +26 -6
  45. package/dist/agents/tools/web-fetch-utils.js.map +1 -1
  46. package/dist/buildstamp.json +1 -1
  47. package/dist/cli/run-main.js +1 -1
  48. package/dist/cli/run-main.js.map +1 -1
  49. package/dist/core/daemon/systemd.js +1 -1
  50. package/dist/core/daemon/systemd.js.map +1 -1
  51. package/dist/core/server.js +1 -1
  52. package/dist/core/server.js.map +1 -1
  53. package/dist/security/media-path-guard.d.ts.map +1 -1
  54. package/dist/security/media-path-guard.js +11 -3
  55. package/dist/security/media-path-guard.js.map +1 -1
  56. package/package.json +1 -1
  57. package/scripts/convex-dev.mjs +24 -6
  58. package/skills/coding-agent/SKILL.md +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"media-path-guard.d.ts","sourceRoot":"","sources":["../../src/security/media-path-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAoCD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAyC3E"}
1
+ {"version":3,"file":"media-path-guard.d.ts","sourceRoot":"","sources":["../../src/security/media-path-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAwCD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CA+C3E"}
@@ -32,9 +32,13 @@ const SENSITIVE_BASENAMES = new Set([
32
32
  "auth-profiles.json",
33
33
  "models.json",
34
34
  "exec-approvals.json",
35
+ // Brigade encryption key (stored outside ~/.brigade by design)
36
+ "encryption.key",
37
+ // Convex local backend admin key
38
+ "admin-key.txt",
35
39
  ]);
36
40
  /** Path fragments that mark a credentials directory (platform-normalized separators). */
37
- const SENSITIVE_DIR_NAMES = [".ssh", ".aws", ".gnupg", ".kube", ".docker", "gcloud"];
41
+ const SENSITIVE_DIR_NAMES = [".ssh", ".aws", ".gnupg", ".kube", ".docker", "gcloud", ".convex-data"];
38
42
  /** Resolved-prefix roots that are off-limits regardless of filename. */
39
43
  function systemRoots() {
40
44
  if (process.platform === "win32") {
@@ -89,8 +93,12 @@ export function validateOutboundMediaPath(rawPath) {
89
93
  }
90
94
  }
91
95
  // Brigade's sealed per-agent auth subtree (…/agents/<id>/agent/…) and any
92
- // auth* file under a .brigade dir — denied regardless of basename.
93
- if (/[\\/]agents[\\/][^\\/]+[\\/]agent[\\/]/.test(resolved) || /[\\/]\.brigade[\\/].*auth/i.test(resolved)) {
96
+ // `auth` path component under a .brigade dir — denied regardless of basename.
97
+ // Walk the already-split segments (linear, no regex backtracking).
98
+ const sealedPerAgent = segments.some((seg, i) => seg === "agents" && i + 2 < segments.length && segments[i + 2] === "agent" && Boolean(segments[i + 1]));
99
+ const brigadeIdx = segments.indexOf(".brigade");
100
+ const authUnderBrigade = brigadeIdx >= 0 && segments.slice(brigadeIdx + 1).some((seg) => seg.includes("auth"));
101
+ if (sealedPerAgent || authUnderBrigade) {
94
102
  return { ok: false, reason: "refusing to attach from the credential store" };
95
103
  }
96
104
  return { ok: true };
@@ -1 +1 @@
1
- {"version":3,"file":"media-path-guard.js","sourceRoot":"","sources":["../../src/security/media-path-guard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"media-path-guard.js","sourceRoot":"","sources":["../../src/security/media-path-guard.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spinabot/brigade",
3
- "version": "1.19.0",
3
+ "version": "1.19.2",
4
4
  "description": "Brigade — your personal AI crew",
5
5
  "homepage": "https://brigade.spinabot.com",
6
6
  "author": "Spinabot <hello@brigade-agent.ai>",
@@ -19,7 +19,7 @@ import { mkdirSync, existsSync, writeFileSync, readFileSync, unlinkSync } from "
19
19
  import { randomBytes } from "node:crypto";
20
20
  import { createServer } from "node:http";
21
21
  import { readFile, stat } from "node:fs/promises";
22
- import { extname, join, dirname, resolve } from "node:path";
22
+ import { extname, join, dirname, resolve, sep } from "node:path";
23
23
  import { fileURLToPath } from "node:url";
24
24
 
25
25
  const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
@@ -235,12 +235,26 @@ const MIME = {
235
235
  ".woff2": "font/woff2",
236
236
  };
237
237
 
238
+ // Confine a request-derived file path under DASHBOARD_DIR. `req.url` is
239
+ // attacker-controllable (any local process can hit 127.0.0.1:6791), so a
240
+ // decoded `..` segment must never let `join` escape the served root. Resolve
241
+ // to an absolute path and reject anything outside DASHBOARD_DIR.
242
+ const DASHBOARD_ROOT = resolve(DASHBOARD_DIR);
243
+ function confineToDashboard(candidate) {
244
+ const resolved = resolve(candidate);
245
+ if (resolved === DASHBOARD_ROOT || resolved.startsWith(DASHBOARD_ROOT + sep)) {
246
+ return resolved;
247
+ }
248
+ return null;
249
+ }
250
+
238
251
  const dashboardServer = createServer(async (req, res) => {
239
252
  try {
240
253
  let urlPath = decodeURIComponent((req.url ?? "/").split("?")[0]);
241
254
  if (urlPath === "/") urlPath = "/index.html";
242
255
 
243
- let filePath = join(DASHBOARD_DIR, urlPath);
256
+ let filePath = confineToDashboard(join(DASHBOARD_DIR, urlPath));
257
+ if (!filePath) { res.writeHead(404); res.end("Not Found"); return; }
244
258
 
245
259
  // SPA fallback — if the requested path has no extension and doesn't exist,
246
260
  // try $path.html, then fall back to index.html.
@@ -248,11 +262,12 @@ const dashboardServer = createServer(async (req, res) => {
248
262
  try { st = await stat(filePath); } catch {}
249
263
  if (!st || st.isDirectory()) {
250
264
  const candidates = [
251
- filePath + ".html",
252
- join(filePath, "index.html"),
253
- join(DASHBOARD_DIR, "index.html"),
265
+ confineToDashboard(filePath + ".html"),
266
+ confineToDashboard(join(filePath, "index.html")),
267
+ join(DASHBOARD_ROOT, "index.html"),
254
268
  ];
255
269
  for (const c of candidates) {
270
+ if (!c) continue;
256
271
  try {
257
272
  const s = await stat(c);
258
273
  if (s.isFile()) { filePath = c; st = s; break; }
@@ -294,8 +309,11 @@ const dashboardServer = createServer(async (req, res) => {
294
309
  }
295
310
  res.end(await readFile(filePath));
296
311
  } catch (err) {
312
+ // Log the detail locally; never echo the raw error (path/stack) to the
313
+ // HTTP response.
314
+ console.error(`\x1b[31m▌ dashboard request failed: ${String(err)}\x1b[0m`);
297
315
  res.writeHead(500);
298
- res.end(String(err));
316
+ res.end("Internal Server Error");
299
317
  }
300
318
  });
301
319
 
@@ -208,7 +208,7 @@ bash pty:true workdir:~/project command:"opencode run 'Your task'"
208
208
  ## Pi Coding Agent
209
209
 
210
210
  ```bash
211
- # Install: npm install -g @mariozechner/pi-coding-agent
211
+ # Install: npm install -g @earendil-works/pi-coding-agent
212
212
  bash pty:true workdir:~/project command:"pi 'Your task'"
213
213
 
214
214
  # Non-interactive mode (PTY still recommended)