You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A link at a project entry is now honored only in the entry's own folder.
The plugin dist changes in lib/repo-fs.js and the version string; the new test cases and the test floor are the room's own tooling.
Security
A file link at a project entry no longer hands another folder's file to the reader(shipped: lib/repo-fs.js). This is the entry-level half of CWK2-026, the E2-4 class (a link in a project path that the reader follows to somewhere the repository chose); 2.8.5 closed the folder-chain half. Until now repoEntryInfo honored a file symlink at a project entry (the project config, the journal file, AGENTS.md, task.md) whenever its real path stayed anywhere inside the project, so a cloned repository could have the reader take a file from another folder through a config name or through AGENTS.md. Now, under a project root, a link is honored only when its target lies in the entry's own folder (path.dirname(realpath(entry)) equals realpath(path.dirname(entry)), both sides through fs.realpathSync.native). Any other link is refused wherever it points, a target in another folder of the project included, and a chain is judged by its final target. A same-folder link still reads (for example AGENTS.md to CLAUDE.md at the root, or coalhearth.json to other.json beside it), and a plain file is unaffected. The user's own home files (the global config and the update stamp) are read with no root and follow links as before. Affected: every release before this one, read in the code, not run on the old tags. Through v2.6.0 the entries were read with a plain fs.readFileSync that follows any link (for example v2.6.0:lib/state-snapshot.js read task.md and AGENTS.md that way; SECURITY.md classes 1 to 4 cover the link that leaves the project); from v2.6.1 to v2.8.5 repoEntryInfo honored any target inside the project (the rule arrived in commit f678ca3, first contained in v2.6.1); the new cases were run with an injected link on Windows 11 with Node 24.19, and the real file-symlink twins of the same cases skip on that volume and run on the project's Linux and macOS CI legs. Fixed in commit 587371e. The new cases in lib/folder-pin.test.js — test: "CWK2-026 entry rule: a file link at the project root whose target is in ANOTHER folder inside the project is refused, never read", "CWK2-026 entry rule: a file link at the config path whose target is in ANOTHER folder inside the project is refused, never read", "CWK2-026 entry rule: a chain whose first hop stays in the folder but whose final target is in another folder is refused", "CWK2-026 entry rule: a file link pointing OUTSIDE the project is refused (kept: green before and after)", "CWK2-026 entry rule: a plain file and a plain folder chain are read as before", "CWK2-026 entry rule: a same-folder link at the project root (AGENTS.md -> CLAUDE.md) is still read", "CWK2-026 entry rule: a same-folder link at the config path (coalhearth.json -> other.json beside it) is still read", and the five injected-link twins that run on every volume: "CWK2-026 entry rule (injected link): a link at the project root to a file in ANOTHER folder inside the project is refused", "CWK2-026 entry rule (injected link): a link at the config path to a file in ANOTHER folder inside the project is refused", "CWK2-026 entry rule (injected link): a link pointing OUTSIDE the project is refused", "CWK2-026 entry rule (injected link): a same-folder link at the project root (AGENTS.md -> CLAUDE.md) is still read", "CWK2-026 entry rule (injected link): a same-folder link at the config path (coalhearth.json -> other.json beside it) is still read".
A named residual: the config read and the configure.mjs write are each a check followed by an open or write. The project-config read and the scripts/configure.mjs write each ask the folder check first and open or write afterwards, so a local process that swaps a just-checked folder for a link in between can have the config read from another place (bounded to a regular file) or the config file or its .bak landed outside the project; the check narrows the window and does not close it (SECURITY.md, class 7). This is reasoning from the code, not a measured result. — test: none (a documented limit, nothing measured).
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
A link at a project entry is now honored only in the entry's own folder.
The plugin dist changes in
lib/repo-fs.jsand the version string; the new test cases and the test floor are the room's own tooling.Security
lib/repo-fs.js). This is the entry-level half of CWK2-026, the E2-4 class (a link in a project path that the reader follows to somewhere the repository chose); 2.8.5 closed the folder-chain half. Until nowrepoEntryInfohonored a file symlink at a project entry (the project config, the journal file,AGENTS.md,task.md) whenever its real path stayed anywhere inside the project, so a cloned repository could have the reader take a file from another folder through a config name or throughAGENTS.md. Now, under a project root, a link is honored only when its target lies in the entry's own folder (path.dirname(realpath(entry))equalsrealpath(path.dirname(entry)), both sides throughfs.realpathSync.native). Any other link is refused wherever it points, a target in another folder of the project included, and a chain is judged by its final target. A same-folder link still reads (for exampleAGENTS.mdtoCLAUDE.mdat the root, orcoalhearth.jsontoother.jsonbeside it), and a plain file is unaffected. The user's own home files (the global config and the update stamp) are read with no root and follow links as before. Affected: every release before this one, read in the code, not run on the old tags. Through v2.6.0 the entries were read with a plainfs.readFileSyncthat follows any link (for examplev2.6.0:lib/state-snapshot.jsreadtask.mdandAGENTS.mdthat way; SECURITY.md classes 1 to 4 cover the link that leaves the project); from v2.6.1 to v2.8.5repoEntryInfohonored any target inside the project (the rule arrived in commitf678ca3, first contained in v2.6.1); the new cases were run with an injected link on Windows 11 with Node 24.19, and the real file-symlink twins of the same cases skip on that volume and run on the project's Linux and macOS CI legs. Fixed in commit587371e. The new cases inlib/folder-pin.test.js— test: "CWK2-026 entry rule: a file link at the project root whose target is in ANOTHER folder inside the project is refused, never read", "CWK2-026 entry rule: a file link at the config path whose target is in ANOTHER folder inside the project is refused, never read", "CWK2-026 entry rule: a chain whose first hop stays in the folder but whose final target is in another folder is refused", "CWK2-026 entry rule: a file link pointing OUTSIDE the project is refused (kept: green before and after)", "CWK2-026 entry rule: a plain file and a plain folder chain are read as before", "CWK2-026 entry rule: a same-folder link at the project root (AGENTS.md -> CLAUDE.md) is still read", "CWK2-026 entry rule: a same-folder link at the config path (coalhearth.json -> other.json beside it) is still read", and the five injected-link twins that run on every volume: "CWK2-026 entry rule (injected link): a link at the project root to a file in ANOTHER folder inside the project is refused", "CWK2-026 entry rule (injected link): a link at the config path to a file in ANOTHER folder inside the project is refused", "CWK2-026 entry rule (injected link): a link pointing OUTSIDE the project is refused", "CWK2-026 entry rule (injected link): a same-folder link at the project root (AGENTS.md -> CLAUDE.md) is still read", "CWK2-026 entry rule (injected link): a same-folder link at the config path (coalhearth.json -> other.json beside it) is still read".configure.mjswrite are each a check followed by an open or write. The project-config read and thescripts/configure.mjswrite each ask the folder check first and open or write afterwards, so a local process that swaps a just-checked folder for a link in between can have the config read from another place (bounded to a regular file) or the config file or its.baklanded outside the project; the check narrows the window and does not close it (SECURITY.md, class 7). This is reasoning from the code, not a measured result. — test: none (a documented limit, nothing measured).Release page · CoalHearth
All reactions