MCPcopy Create free account
hub / github.com/EvoMap/evolver / _writeWorkspaceIdToFs

Function _writeWorkspaceIdToFs

src/gep/paths.js:369–419  ·  view source on GitHub ↗
(file, id)

Source from the content-addressed store, hash-verified

367// (or generate one if `id` is null). Returns the id that ended up on
368// disk, or null on any unrecoverable error. EEXIST races re-read.
369function _writeWorkspaceIdToFs(file, id) {
370 const dir = path.dirname(file);
371 try {
372 // Refuse to write if `.evolver` is a symlink. mkdirSync({recursive:true})
373 // happily traverses an existing symlinked directory and the subsequent
374 // open() lands the secret file in the attacker-controlled target —
375 // O_NOFOLLOW only guards the FINAL path component, not intermediate
376 // directories. The pre-refactor monolithic getWorkspaceId() returned
377 // null on a symlinked dir before reaching the write; preserve that
378 // here (Bugbot PR #121 round-1 HIGH; original guard PR #109 round-2 HIGH).
379 const dirStat = fs.lstatSync(dir, { throwIfNoEntry: false });
380 if (dirStat && dirStat.isSymbolicLink()) return null;
381 fs.mkdirSync(dir, { recursive: true });
382 const payload = id || require('crypto').randomBytes(16).toString('hex');
383 // Atomic create-and-fail-if-exists so we never overwrite an
384 // attacker-pre-placed file (TOCTOU between lstat and writeFileSync
385 // could otherwise race a symlink in). O_NOFOLLOW also refuses to
386 // follow a symlink that appears between the lstat and open. Both
387 // flags exist on Linux/macOS; on Windows O_NOFOLLOW is silently
388 // ignored, but Windows has no symlink-by-default risk.
389 // NOTE(windows): mode 0o600 passed to openSync is silently ignored on
390 // Windows. The workspace-id file will NOT be restricted to owner-read-only.
391 // Only Windows user-profile directory ACLs provide isolation. To get
392 // proper per-user encryption on Windows, install @napi-rs/keyring — the
393 // keychain path above will store the id in Credential Manager (DPAPI)
394 // instead of this plaintext file.
395 const flags = fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL |
396 (fs.constants.O_NOFOLLOW || 0);
397 let fd;
398 try {
399 fd = fs.openSync(file, flags, 0o600);
400 } catch (e) {
401 if (e && e.code === 'EEXIST') {
402 // Another process beat us — re-read with the same symlink guards.
403 return _readWorkspaceIdFromFs(file);
404 }
405 // ELOOP / EMLINK from O_NOFOLLOW hitting a symlink — refuse.
406 return null;
407 }
408 try {
409 fs.writeSync(fd, payload + '\n', 0, 'utf8');
410 } finally {
411 fs.closeSync(fd);
412 }
413 // Best-effort chmod: silently ignored on Windows (no equivalent ACL API).
414 try { fs.chmodSync(file, 0o600); } catch { /* best-effort; no-op on Windows */ }
415 return payload;
416 } catch {
417 return null;
418 }
419}
420
421function getWorkspaceId() {
422 if (process.env.EVOLVER_WORKSPACE_ID) return String(process.env.EVOLVER_WORKSPACE_ID);

Callers 1

getWorkspaceIdFunction · 0.85

Calls 1

_readWorkspaceIdFromFsFunction · 0.85

Tested by

no test coverage detected