OpenKnowledge
Changelog

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 via git clone/pull of an untrusted branch) let GET /api/folder-config disclose any YAML file the server process could read (for example ~/.config/gh/hosts.yml or ~/.kube/config) as folder frontmatter, and one PUT /api/folder-config folded 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/templates directory reached by requesting a descendant folder — similarly let GET /api/template return the link target's raw bytes verbatim, and a symlinked <folder>/.ok directory aliased both endpoints into another directory. The seed/ok init path 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>/.ok on the requested folder on every folder-config, template, and folder-history arm, and — on the template arms, reads AND writes — a symlinked <folder>/.ok/templates directory, a symlinked template leaf (GET refuses to read through it; PUT/import refuse to write through it), and a symlinked ancestor .ok/.ok/templates on the fetch-by-name walk, all with urn:ok:error:symlink-refused. The folder-config arms degrade instead of rejecting for the template menu: a symlinked .ok/templates on the requested folder (wherever it points, dangling included), or a symlinked .ok/.ok/templates on any ancestor it inherits from, is skipped by the menu and reported by GET /api/folder-config via warnings + warningCodes (templates-symlink-refused, or templates-unverifiable when its lstat fails with anything but ENOTDIR; a non-directory .ok or .ok/templates, on this folder or an ancestor, provably holds no templates and produces no templates-* code);
    • reports a symlinked, malformed, or uninspectable frontmatter.yml in GET /api/folder-config via warnings + warningCodes (symlink-refused / malformed-yaml / unverifiable, with frontmatter_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/templates link that resolves outside the content root (was 400 path-escape), a regular file named .ok, and a .ok directory the server cannot search (both were 500). All three now answer 200 on GET /api/folder-config and on GET /api/history?folder=. GET /api/folder-config names what it dropped in warnings + warningCodestemplates-symlink-refused for the first, unverifiable for the second, templates-unverifiable + unverifiable for the third; GET /api/history?folder= has no warnings field, so it simply answers. PUT /api/folder-config still fails a folder whose .ok is a regular file or is unsearchable, now from the write itself rather than path validation; it no longer rejects a folder whose own .ok/templates resolves outside the content root, since the write never reads or writes that path. Those arms no longer run the .ok/templates containment check: the unconditional check on <folder>/.ok already covers every escape through an ancestor or .ok itself, and a symlinked .ok/templates is refused by identity in collectFromFolder before 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/templates on the source folder's walk cannot be inspected, matching GET /api/template, where it previously fell through to a misleading 404 template-not-found.

    This is a blanket refusal of symlinks at .ok artifact paths on the HTTP plane, broader than the earlier escaping-symlink fixes: an in-root .ok symlink 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/ (the frontmatter.yml leaf, the .ok or templates directory, or a template file) with a regular file.

View v0.70.4 on GitHub