Skip to content

fix: restrict ~/.openwiki ACLs on Windows where chmod is a no-op#367

Open
Wenyu Chiou (WenyuChiou) wants to merge 1 commit into
langchain-ai:mainfrom
WenyuChiou:fix/windows-openwiki-home-acl
Open

fix: restrict ~/.openwiki ACLs on Windows where chmod is a no-op#367
Wenyu Chiou (WenyuChiou) wants to merge 1 commit into
langchain-ai:mainfrom
WenyuChiou:fix/windows-openwiki-home-acl

Conversation

@WenyuChiou

Copy link
Copy Markdown

What

Adds restrictDirToCurrentUser (src/windows-acl.ts) and wires it into the two places that express the home directory's 0o700 owner-only intent — ensureOpenWikiHome and saveOpenWikiEnv:

  • On win32, runs icacls <dir> /grant:r <user>:(OI)(CI)F *S-1-5-18:(OI)(CI)F, then icacls <dir> /inheritance:r — full control for the current user and SYSTEM (well-known SID, language-independent), inheritable so newly created children (.env, openwiki.sqlite, connectors/**) are covered, inherited ACEs removed.
  • Fail-safe ordering: the grant runs before the inheritance reset, so a failed grant can never lock the user out of the directory.
  • Best-effort by design: returns false instead of throwing (mirroring the surrounding chmodIfExists semantics) — a machine without working icacls never fails a run.
  • No new dependencies; no-op on non-Windows platforms, so POSIX behavior is completely unchanged.

Why

On Windows, Node's fs.chmod only toggles the read-only attribute and the mode option on mkdir/writeFile is ignored — so the existing 0o700/0o600 calls protect nothing there, and ~/.openwiki (plaintext .env with every provider key and the ChatGPT refresh token, sqlite chat checkpoints, raw connector dumps) simply inherits its parent's ACL.

Verified on a real Windows 11 machine (machine name redacted). A fresh directory before/after the helper:

BEFORE (inherited from parent):
  ... a dozen inherited ACEs with (M) modify rights, including sandbox users ...
  NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
  BUILTIN\Administrators:(I)(OI)(CI)(F)
  MACHINE\user:(I)(OI)(CI)(F)

AFTER restrictDirToCurrentUser:
  NT AUTHORITY\SYSTEM:(OI)(CI)(F)
  MACHINE\user:(OI)(CI)(F)

Scope notes, stated explicitly: pre-existing files keep the ACEs they already inherited (no recursive /T pass — new children inherit the restricted ACL; a recursive apply on a large connectors/raw tree could be slow and is easy to add later if wanted). Administrators lose their inherited ACE on the directory but can still take ownership — the same way root bypasses 0o700 on POSIX.

How tested

  • New test/windows-acl.test.ts (3 tests, mocked node:child_process, runs on any platform incl. ubuntu CI): non-win32 no-op; exact grant + inheritance-reset argument sequence with grant ordered first; grant failure short-circuits without removing inheritance (the lockout guard).
  • Real-machine integration check on Windows 11: icacls output before/after shown above.
  • pnpm run format, pnpm run lint, pnpm test: 298/300 pass locally on Windows; the 2 failures are the pre-existing win32 test/env-behavior.test.ts platform checks (they reproduce on pristine main) — notably, this PR is the change that makes the intent of those 0600 expectations real on Windows at the ACL layer.

Fixes #366

🤖 Generated with Claude Code

The OpenWiki home directory is created with mode 0o700 and chmod'd to
0o700 wherever it is ensured, but on Windows Node's chmod only toggles
the read-only attribute - the directory holding ~/.openwiki/.env (every
provider API key and OAuth refresh token in plaintext), the sqlite chat
checkpoints, and raw connector dumps simply inherits whatever ACL its
parent grants.

restrictDirToCurrentUser mirrors the existing 0o700 owner-only intent
with icacls: grant full control to the current user and SYSTEM (by
well-known SID, language-independent), inheritable so new children are
covered, then remove inherited ACEs. The grant runs before the
inheritance reset so a failed grant can never lock the user out, and
the whole helper is best-effort (returns false, never throws) exactly
like the surrounding chmod calls. No-op on non-Windows platforms.

Wired into ensureOpenWikiHome and saveOpenWikiEnv, the two places that
express the 0o700 intent on the home directory.

Verified on a real Windows 11 machine: a fresh temp directory carrying
a dozen inherited modify-rights ACEs was reduced to exactly
NT AUTHORITY\SYSTEM and the current user with (OI)(CI)(F).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: ~/.openwiki permissions are a no-op on Windows — chmod 0o700/0o600 leaves the credential store on inherited ACLs

1 participant