Security¶
This page covers what data Paperless NGX Dedupe touches, where it can send document content, what its Paperless-NGX credential needs, and where secrets live.
Early development
Paperless NGX Dedupe is not production-ready. Do not point it at a Paperless-NGX instance you care about without a backup — see Getting Started.
Paperless-NGX credentials¶
Authenticate with PAPERLESS_API_TOKEN (preferred) or PAPERLESS_USERNAME + PAPERLESS_PASSWORD. If both are set, the token is used first. These values are entirely environment-owned: the Settings page exposes the configured URL as read-only and only reports whether authentication is configured — it never reads, stores, exports, or accepts these values through the database or configuration API. See Configuration — Core Runtime.
Required permissions¶
What the credential needs depends on which features you use:
- Sync and analysis only read documents and their text (
GET /api/documents/,GET /api/documents/{id}/) — a read-only account is sufficient for these. - Applying AI suggestions patches documents (
PATCH /api/documents/{id}/) and, unlesscreateMissingEntities: falseis passed, creates missing correspondents, document types, and tags. See AI Processing — Applying Suggestions. - Batch delete removes non-primary documents from reviewed duplicate groups. See Architecture — Review Flow.
- Paperless-NGX system metrics (
PAPERLESS_METRICS_ENABLED) requirepaperless.view_system_monitoringfor thestatuscollector, andpaperless.view_global_statisticsfor library-wide totals from thestatisticsanddocumentcollectors — without it, Paperless-NGX scopes those counts to what the API user can see. See Paperless-NGX 3 Compatibility — Metrics Permissions.
The Troubleshooting guide notes that admin-level tokens work best in practice; scope a dedicated Paperless-NGX account down from there based on which of the above features you actually use.
Where document content can leave the deployment¶
Synced document text and metadata are stored locally in the application's own SQLite database and are not sent anywhere by sync or analysis — MinHash/LSH scoring runs entirely inside the container.
The one path that sends document content outside the deployment is AI processing, and it is off by default. Enabling it (AI_ENABLED=true plus AI_OPENAI_API_KEY) sends each processed document's text — truncated to maxContentLength (8,000 characters by default) — to OpenAI for metadata extraction. If includeCorrespondents, includeDocumentTypes, or includeTags are also enabled, the existing names for those fields are sent as reference data alongside the document text. See AI Processing.
AI results are stored as pending_review and are never applied to Paperless-NGX automatically — scheduled AI processing creates suggestions for review only. See AI Processing — Status Lifecycle.
Optional OpenTelemetry traces/metrics/logs, Grafana Faro frontend telemetry, and Pyroscope profiles are separate, independent telemetry paths that you configure with your own OTLP endpoint — see Observability. Enabling them is unrelated to, and does not require, the AI path above.
Secrets and storage¶
- Paperless-NGX credentials, the OpenAI API key, and OTLP/Pyroscope credentials are all environment variables — none are written to the SQLite database.
- Config backup/restore (
GET /api/v1/export/config.json,POST /api/v1/import/config) covers mutable app and dedup settings only; environment-owned credentials are excluded. See API Reference — Export / Import. - Existing legacy credential rows in
app_configare removed during startup migration. See Configuration — Core Runtime. - The database backup downloaded from Settings > Database backup does not contain Paperless connection credentials, but it does contain synced document metadata, duplicate decisions, and AI review state. Store and delete downloaded copies with the same access controls as the live database. See Database Backup and Restore.
Network exposure¶
CORS_ALLOW_ORIGINdefaults to empty (same-origin only). Setting it to*allows cross-origin requests to the API — only do this if you understand the exposure. See Configuration — Core Runtime.- SvelteKit's CSRF protection requires
ORIGINto match the URL users access the app at, particularly behind a reverse proxy. See Troubleshooting — ORIGIN environment variable. - If your Paperless-NGX instance uses a self-signed certificate, setting
NODE_TLS_REJECT_UNAUTHORIZED=0to bypass the resulting Node.js TLS error is explicitly documented as not recommended for production. See Troubleshooting — SSL/TLS errors.
Container runtime¶
The production image runs its entrypoint as root only long enough to chown the data directory, then drops privileges via gosu to the configured PUID/PGID (both default to 1000) before executing the application. Do not run multiple application containers against the same SQLite file. See Upgrading.
Every push to main and a weekly schedule run hadolint against the Dockerfile and Trivy filesystem/misconfiguration scanning, with results uploaded to the repository's GitHub Security tab.
Reporting a vulnerability¶
Report security vulnerabilities via GitHub Security Advisories on the repository rather than a public issue.