v0.70.4
Patch Changes
The folder-config, template, and folder Activity (
/api/history) endpoints now refuse to read or write through symbolic links planted in a folder's.ok/directory. Previously, a maliciously committed symlink at<folder>/.ok/frontmatter.yml(arriving viagit clone/pull of an untrusted branch) letGET /api/folder-configdisclose any YAML file the server process could read (for example~/.config/gh/hosts.ymlor~/.kube/config) as folder frontmatter, and onePUT /api/folder-configfolded the link target's keys into the merge and replaced the link with a real, git-trackable file containing that foreign content. A symlink at<folder>/.ok/templates/<name>.md— or a symlinked.ok/.ok/templatesdirectory reached by requesting a descendant folder — similarly letGET /api/templatereturn the link target's raw bytes verbatim, and a symlinked<folder>/.okdirectory aliased both endpoints into another directory. The seed/ok initpath could also create a file outside the project by writing through a committed dangling symlink at a scaffolded leaf.The server now:
- rejects a symlinked
<folder>/.okon the requested folder on every folder-config, template, and folder-history arm, and — on the template arms, reads AND writes — a symlinked<folder>/.ok/templatesdirectory, a symlinked template leaf (GETrefuses to read through it;PUT/import refuse to write through it), and a symlinked ancestor.ok/.ok/templateson the fetch-by-name walk, all withurn:ok:error:symlink-refused. The folder-config arms degrade instead of rejecting for the template menu: a symlinked.ok/templateson the requested folder (wherever it points, dangling included), or a symlinked.ok/.ok/templateson any ancestor it inherits from, is skipped by the menu and reported byGET /api/folder-configviawarnings+warningCodes(templates-symlink-refused, ortemplates-unverifiablewhen itslstatfails with anything butENOTDIR; a non-directory.okor.ok/templates, on this folder or an ancestor, provably holds no templates and produces notemplates-*code); - reports a symlinked, malformed, or uninspectable
frontmatter.ymlinGET /api/folder-configviawarnings+warningCodes(symlink-refused/malformed-yaml/unverifiable, withfrontmatter_local: null) while the rest of the folder payload keeps working, and treats such a leaf — or a symlinked containing.ok— as absent in folder-metadata enrichment and template-menu enumeration; - writes scaffolded files with
O_EXCL, so a committed dangling symlink at a seeded leaf fails rather than writing through; - degrades instead of erroring on the folder-config and folder Activity arms for three shapes the path gate used to reject: a folder's own
.ok/templateslink that resolves outside the content root (was 400path-escape), a regular file named.ok, and a.okdirectory the server cannot search (both were 500). All three now answer 200 onGET /api/folder-configand onGET /api/history?folder=.GET /api/folder-confignames what it dropped inwarnings+warningCodes—templates-symlink-refusedfor the first,unverifiablefor the second,templates-unverifiable+unverifiablefor the third;GET /api/history?folder=has nowarningsfield, so it simply answers.PUT /api/folder-configstill fails a folder whose.okis a regular file or is unsearchable, now from the write itself rather than path validation; it no longer rejects a folder whose own.ok/templatesresolves outside the content root, since the write never reads or writes that path. Those arms no longer run the.ok/templatescontainment check: the unconditional check on<folder>/.okalready covers every escape through an ancestor or.okitself, and a symlinked.ok/templatesis refused by identity incollectFromFolderbefore anything under it is enumerated. The template arms keep both checks; - returns 500 (carrying the errno) from
POST /api/template(move) when an ancestor.ok/.ok/templateson the source folder's walk cannot be inspected, matchingGET /api/template, where it previously fell through to a misleading 404template-not-found.
This is a blanket refusal of symlinks at
.okartifact paths on the HTTP plane, broader than the earlier escaping-symlink fixes: an in-root.oksymlink is refused too, because the folder-config write merges and rewrites the leaf in place. If a folder's properties, its template picker, or its Activity feed stop resolving after upgrading, replace the symlink under that folder's.ok/(thefrontmatter.ymlleaf, the.okortemplatesdirectory, or a template file) with a regular file.- rejects a symlinked