From 39d9be30f9f443de597a9f5d6fe59f2d1d9609ba Mon Sep 17 00:00:00 2001 From: neon <18559658+neonsolstice@users.noreply.github.com> Date: Tue, 7 Jul 2026 17:02:46 +0000 Subject: [PATCH] feat(library): support LIBRARY_BROWSE_ROOT to restrict file path access Introduce a LIBRARY_BROWSE_ROOT environment variable (defaulting to the current directory) to restrict directories users can browse and select when setting up library paths. Add a PathPolicyService on the backend to enforce path containment checks securely, and update the frontend FolderPickerModal to prevent navigating above the configured browse root. Closes #567 --- .env.example | 4 + README.md | 2 + .../library/components/FolderPickerModal.vue | 64 ++++++++++--- .../__tests__/FolderPickerModal.spec.ts | 91 +++++++++++++++++++ docker-compose.yml | 1 + docs/DEVELOPMENT.md | 19 ++-- packages/types/src/path.ts | 4 + server/.env.example | 4 + server/src/config/config.test.ts | 15 +++ server/src/config/config.ts | 2 + server/src/config/env.validation.test.ts | 18 ++++ server/src/config/env.validation.ts | 4 + server/src/modules/library/library.module.ts | 11 ++- .../modules/library/library.service.test.ts | 43 ++++++++- server/src/modules/library/library.service.ts | 32 +++++-- .../modules/path/path-policy.service.test.ts | 67 ++++++++++++++ .../src/modules/path/path-policy.service.ts | 78 ++++++++++++++++ .../src/modules/path/path.controller.test.ts | 11 ++- server/src/modules/path/path.controller.ts | 11 ++- server/src/modules/path/path.module.test.ts | 4 +- server/src/modules/path/path.module.ts | 4 +- server/src/modules/path/path.service.test.ts | 34 ++++++- server/src/modules/path/path.service.ts | 19 +++- .../route-inventory/manifest.json | 4 +- .../route-inventory/routes-05.json | 12 +++ 25 files changed, 515 insertions(+), 43 deletions(-) create mode 100644 client/src/features/library/components/__tests__/FolderPickerModal.spec.ts create mode 100644 server/src/modules/path/path-policy.service.test.ts create mode 100644 server/src/modules/path/path-policy.service.ts diff --git a/.env.example b/.env.example index 76a483d8f..c1cd00adb 100644 --- a/.env.example +++ b/.env.example @@ -40,6 +40,10 @@ NODE_MAX_OLD_SPACE_SIZE=2048 # CORS origin for the frontend when served from a different domain than APP_URL # CLIENT_URL=https://app.example.com +# Container folder used as the top of the library creation folder picker. +# Defaults to / when unset. Set to /books to hide other container root folders. +# LIBRARY_BROWSE_ROOT=/books + # Set to false only if your platform manages bind mount ownership externally. # BOOKORBIT_FIX_PERMISSIONS=true diff --git a/README.md b/README.md index e42dd87c7..976f31774 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,8 @@ JWT_SECRET= # signs login tokens - openssl rand -hex 32 SETUP_BOOTSTRAP_TOKEN= # one-time setup wizard token - openssl rand -hex 16 ``` +Optionally set `LIBRARY_BROWSE_ROOT=/books` to start the library folder picker at `/books` instead of `/`. + Then start: ```bash diff --git a/client/src/features/library/components/FolderPickerModal.vue b/client/src/features/library/components/FolderPickerModal.vue index ca9cb2b7d..0f7aac862 100644 --- a/client/src/features/library/components/FolderPickerModal.vue +++ b/client/src/features/library/components/FolderPickerModal.vue @@ -1,7 +1,7 @@