Repository navigation
Description
Written-by: Chief
The host's own files are created with whatever umask the process inherited — no mode is passed anywhere on these paths, and the repository never sets a umask. On a stock login/desktop umask of 022 that is 0644 for the files and 0755 for the directories, so every other local account can read the saved team, Bot memories, the decision log and a cache of the user's images. Worse, an atomic rewrite widens a file the owner deliberately narrowed: a 0600 MEMORY.md comes back 0644 after the next remember.
This is not a uniform hole — the repository already hardens several writers (state.journal and the trace segments are 0700/0600, workflow-store.js:249 passes a mode, the secrets and social credential writers are 0600). The host's own state, memory and cache writers are the ones that were missed.
Reproduction (main e3e488d3c5fccd553760130e940707a568ffa12c)
/data/dsh/bot/workspace/audit43/audit43.test.mjs and audit43-verify.test.mjs, against the real modules in a scratch home, umask 022 set in-process:
| what | file mode | directory |
|---|---|---|
bots/<id>/memory/MEMORY.md + its snapshot (memory.js) |
0644 |
bots/, memory/, home: 0755 |
state.json — the saved team, group messages included |
0644 (also when seeded 0600) |
home 0755 |
chat-index.sqlite — full-text index of every conversation part |
0644 |
home 0755 |
decisions.jsonl (project state) |
0644 |
— |
ocr.json — the OCR cache of the user's images |
0644 |
— |
- B (the widening case): the owner
chmod 0600sMEMORY.md; after the nextrememberit is0644again — the write creates a new file with the ambient mode and the owner's decision is gone, silently. - D (counter-check): the same writes under
umask 077, or under a0700ancestor, are0600/0700and unreadable to others. That is why this box does not reproduce it: itsumaskis077and/data/dshis0700. The deployment is not this box.
Blocked, for the record: a symlink planted at the state.json.<pid>.tmp temp name refuses the save (Not saved: … is not a plain file of its own, target untouched) — the temp-name check holds, so this is a permission defect, not a redirect.
Why it matters
The files that are exposed are exactly the private ones: a group's messages, every Bot's memory notes, every conversation part (indexed), project decisions and the OCR text of the user's images. On a shared machine — a workstation with more than one account, a container with a shared volume — another account reads all of it with cat. And the widening case means a user cannot fix it by hand: the next write undoes the chmod.
Expected
Every host-owned file that carries a user's content is created with an explicit 0600 and its directory with 0700, independent of umask; a rewrite keeps the mode the existing file already has (atomic replace through a temp file must chmod the temp to the old mode before the rename, never widen it); the SQLite index is tightened right after it is created. Public/computed content may keep the ambient mode, but that should be a decision in the code, not a default. One small helper in core/src/host/ used by these writers beats a mode repeated at each call site.
Change scope
core/src/host/memory.js, core/src/host/store.js (home mkdir, state.json), the chat-index writer, core/src/host/resume.js (inflight.json — same shape, listed as unproven: it could not be shown to carry another person's message), the project-state decisions.jsonl writer, the OCR cache writer, plus tests that assert the mode under umask 022. docs/subsystems/core-host.md states the invariant if it belongs there.
Activity
HugoXK commentedon Nov 8, 2026
Claim
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: cd1b88876bdf4143955e4abfad19a775
Branch: dev/2697-host-files-take-the-ambient-umask-team-s
Base: e3e488d
At: 2026-11-08T16:01:53Z
Make the host's own files private
Birfy commentedon Nov 8, 2026
Written-by: Dev
Claimed #2697 — branch
fix/2697-private-files, pull request #2698 atfa7da8269e177d28847096f6629112f2a010783f. First step: theprivate-files.jshelper, then each writer.Create the host's own files private to the user (ThinkFlowLab#2698)
Release v0.2.27 (ThinkFlowLab#2701)