@beastmode-develeap/beastmode 0.1.314 → 0.1.316

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
@@ -5257,11 +5257,43 @@ var init_chat_handler = __esm({
5257
5257
 
5258
5258
  // src/cli/ui/board-api-routes.ts
5259
5259
  import { readFileSync as readFileSync13, writeFileSync as writeFileSync13, existsSync as existsSync16, readdirSync as readdirSync8, unlinkSync as unlinkSync4, mkdirSync as mkdirSync12, statSync as statSync6, rmSync as rmSync3 } from "fs";
5260
- import { join as join14, basename as basename5, resolve as resolve4, dirname as dirname5 } from "path";
5260
+ import { join as join14, basename as basename5, resolve as resolve4, dirname as dirname5, sep } from "path";
5261
5261
  import { homedir } from "os";
5262
5262
  import { randomUUID as randomUUID2 } from "crypto";
5263
5263
  import { execSync as execSync3, spawnSync } from "child_process";
5264
5264
  import http2 from "http";
5265
+ function _getAllowedRoots() {
5266
+ const roots = [];
5267
+ const homeRaw = process.env.HOME && process.env.HOME.length > 0 ? process.env.HOME : homedir();
5268
+ roots.push(resolve4(homeRaw));
5269
+ const projectDir = process.env.PROJECT_DIR;
5270
+ if (projectDir && projectDir.length > 0) {
5271
+ roots.push(resolve4(projectDir));
5272
+ }
5273
+ const cloneDir = process.env.BEASTMODE_CLONE_DIR;
5274
+ if (cloneDir && cloneDir.length > 0) {
5275
+ roots.push(resolve4(cloneDir));
5276
+ }
5277
+ const seen = /* @__PURE__ */ new Set();
5278
+ const deduped = [];
5279
+ for (const r of roots) {
5280
+ if (!seen.has(r)) {
5281
+ seen.add(r);
5282
+ deduped.push(r);
5283
+ }
5284
+ }
5285
+ return deduped;
5286
+ }
5287
+ function _isPathAllowed(targetPath, roots) {
5288
+ if (roots.length === 0) return false;
5289
+ const target = resolve4(targetPath);
5290
+ for (const r of roots) {
5291
+ const root = resolve4(r);
5292
+ if (target === root) return true;
5293
+ if (target.startsWith(root + sep)) return true;
5294
+ }
5295
+ return false;
5296
+ }
5265
5297
  function assertSafeName(name) {
5266
5298
  if (!name || /[/\\]/.test(name) || name === "." || name === "..") {
5267
5299
  throw new Error(`Invalid name: ${name}`);
@@ -6308,6 +6340,12 @@ function getBoardRoutes(factoryDir) {
6308
6340
  const { path: queryPath } = body || {};
6309
6341
  const startPath = queryPath || homedir();
6310
6342
  const target = resolve4(startPath);
6343
+ const allowedRoots = _getAllowedRoots();
6344
+ if (!_isPathAllowed(target, allowedRoots)) {
6345
+ throw new Error(
6346
+ `Path not allowed: ${target} is outside the configured allowlist`
6347
+ );
6348
+ }
6311
6349
  if (!existsSync16(target)) throw new Error(`Path not found: ${target}`);
6312
6350
  const st = statSync6(target);
6313
6351
  if (!st.isDirectory()) throw new Error(`Not a directory: ${target}`);