Skip to content

Make the SQLite data directory and DB files private (0700/0600) - #135

Merged
AdamXweb merged 2 commits into
mainfrom
fix/data-dir-permissions
Jul 23, 2026
Merged

Make the SQLite data directory and DB files private (0700/0600)#135
AdamXweb merged 2 commits into
mainfrom
fix/data-dir-permissions

Conversation

@adamXbot

Copy link
Copy Markdown
Collaborator

Summary

The data directory was created with umask permissions (typically 0755) and better-sqlite3 created privacy.db + its WAL/SHM sidecars 0644 — world-readable on multi-user machines, for a file holding the user's full app inventory, notes, and AI provider key. The repo already sets 0600 on the backup signing key; this brings the database itself up to the same standard.

  • lib/db.ts — the data dir is created with mode: 0o700, and every open runs tightenDataPermissions(): 0700 on the dir, 0600 on privacy.db/-wal/-shm. It runs before the journal_mode=WAL pragma so freshly-created sidecar files inherit 0600 (SQLite copies the main DB file's mode). Best-effort by design: a no-op on Windows, never fatal to opening the DB. Existing loose installs are tightened on their next boot — no migration step needed.
  • src-tauri/src/sidecar.rscfg(unix) 0700 on the data dir at creation, so a desktop first-boot is never world-listable even before the Node side opens the DB.
  • .github/workflows/ci.yml — the compose-smoke bind-mount assertion becomes sudo test -f data/privacy.db: the runner user can no longer stat inside a 0700 dir owned by uid 100, which is the intended lockdown, and the assertion must not depend on its absence.
  • AGENTS.md — documents the permissions contract (including that bind-mount hosts now need sudo to inspect ./data).

Deployment impact

  • Docker named volume (default): none — the audit user (uid 100) owns /app/data and keeps full access.
  • Docker bind mount (opt-in): the host user now needs sudo to look inside ./data. Backups via docker compose cp web:/app/data ./data-backup are unaffected.
  • Desktop (Tauri) and bare next start: files become private to the owning user; no behaviour change for the app itself.

Verification

  • tests/app/data-dir-permissions.test.ts pins three paths: fresh install, loose-install migration (chmod back to 0755/0644, tighten, re-assert), and WAL-sidecar inheritance after a write. POSIX-only, skipped on Windows.
  • 445 unit tests, 0 failures; pnpm typecheck + pnpm lint clean; cargo check --no-default-features --locked clean.
  • The Docker paths are exercised by the compose-smoke job in this PR's own CI run (both volume legs).

🤖 Generated with Claude Code

adamXbot and others added 2 commits July 23, 2026 14:20
The data dir was created with umask perms (typically 0755) and
better-sqlite3 created privacy.db and its WAL/SHM sidecars 0644 —
world-readable on multi-user machines, for a file holding the user's
full app inventory, notes, and AI provider key.

- lib/db.ts: mkdir with mode 0o700, plus tightenDataPermissions() on
  every open (0700 dir, 0600 db/-wal/-shm). Runs BEFORE the WAL
  pragma so freshly-created sidecar files inherit 0600 (SQLite copies
  the main DB file's mode). Best-effort by design: no-op on Windows,
  never fatal to opening the DB. Existing loose installs are tightened
  on their next boot.
- src-tauri/src/sidecar.rs: cfg(unix) 0700 on the data dir at
  creation, so the first boot is never world-listable.
- ci.yml compose-smoke: the bind-mount assertion becomes
  `sudo test -f` — the runner user can no longer stat inside a 0700
  dir owned by uid 100, which is the intended lockdown.
- AGENTS.md: documents the permissions contract.

Pinned by tests/app/data-dir-permissions.test.ts (fresh install,
loose-install migration, WAL-sidecar inheritance).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The quality job's audit gate fails on every branch since today's
advisory batch — none of it introduced by this PR's diff:

- next 16.2.9 -> 16.2.11: patches the 2026-07-22 Next.js batch
  (4 high + 5 moderate, all fixed in 16.2.11)
- dompurify 3.4.11 -> 3.4.12: GHSA-c2j3-45gr-mqc4 (low)
- sharp forced to ^0.35.0 via the existing pnpm-workspace.yaml
  overrides block: Next still pins ^0.34.5 transitively, which audit
  rejects for GHSA-f88m-g3jw-g9cj (libvips CVEs, fixed in 0.35.0).
  Same pattern as the postcss / @babel/core overrides; drop when
  Next's own range reaches >=0.35.

Verified: pnpm audit --prod clean, typecheck, 438 unit tests, full
Playwright suite (33 passed / 1 intentional skip) on a clean
production build of next 16.2.11 with sharp 0.35.3.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@adamXbot

Copy link
Copy Markdown
Collaborator Author

Second commit (79daeb5) is the same fix(deps) advisory patch as on #134 — cherry-picked so this branch passes the pnpm audit --prod gate independently of #134's merge order. Whichever PR merges second rebases cleanly (identical patches are skipped).

🤖 Generated with Claude Code

@AdamXweb
AdamXweb merged commit 0cf68f4 into main Jul 23, 2026
16 checks passed
@AdamXweb
AdamXweb deleted the fix/data-dir-permissions branch July 23, 2026 12:39
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.

2 participants