Security Considerations for Open Notebook: Authentication, Encryption, and Deployment Hardening

Open Notebook implements privacy-first defaults including optional password authentication, Fernet AES-128 encryption for AI provider credentials, and Docker secret support, but production deployments require HTTPS, strict CORS configuration, and network-level hardening to mitigate known limitations.

The lfnovo/open-notebook project provides a privacy-focused knowledge management system, but understanding the security considerations for open-notebook deployments is critical before exposing instances to untrusted networks. While the codebase includes robust encryption for API keys and optional password protection, proper configuration of environment variables and middleware is essential to achieve production-grade security.

Password Authentication Implementation

In api/routers/auth.py, Open Notebook implements an optional single-password authentication scheme. When the environment contains OPEN_NOTEBOOK_PASSWORD or its Docker secret variant OPEN_NOTEBOOK_PASSWORD_FILE, the PasswordAuthMiddleware registered in api/main.py intercepts every request to /api/* endpoints.

The middleware requires an Authorization: Bearer <password> header for all protected routes. Exempted paths include /health, /docs, and /openapi.json to support monitoring and API discovery without credentials.

Check the authentication status:

curl http://localhost:5055/api/auth/status

# → {"auth_enabled":true,"message":"Authentication is required"}

Access protected endpoints using the bearer token:

curl -H "Authorization: Bearer $OPEN_NOTEBOOK_PASSWORD" \
     http://localhost:5055/api/notebooks

Python client implementation:

import requests

class OpenNotebookClient:
    def __init__(self, base_url: str, password: str):
        self.base_url = base_url
        self.headers = {"Authorization": f"Bearer {password}"}

    def list_notebooks(self):
        r = requests.get(f"{self.base_url}/api/notebooks", headers=self.headers)
        return r.json()

# usage

client = OpenNotebookClient("http://localhost:5055", "my_secure_password")
print(client.list_notebooks())

Credential Encryption at Rest

Open Notebook encrypts all AI-provider credentials using Fernet symmetric encryption (AES-128-CBC with HMAC-SHA256 authentication) before storage in SurrealDB. The implementation in open_notebook/utils/encryption.py handles both cryptographic operations and secret retrieval via the get_secret_from_env helper.

The system strictly enforces the presence of OPEN_NOTEBOOK_ENCRYPTION_KEY. Without this key, the application refuses to save or read provider credentials, preventing accidental plain-text storage in the database.

When a user adds an AI provider key via the Settings UI, the backend calls open_notebook/utils/encryption.encrypt_secret, which encrypts the blob before persistence. Retrieval operations use the corresponding decrypt function with the same key.

CORS Configuration and Network Hardening

By default, the FastAPI application in api/main.py configures CORS_ORIGINS="*", allowing any origin to access the API. While convenient for development, this represents a significant security risk for production deployments. The startup sequence logs a warning when the wildcard origin remains active.

Restrict cross-origin access in production:

export CORS_ORIGINS="https://notebook.example.com"

# then restart the API container

Network-level protections complement application security. The documentation recommends binding services to 127.0.0.1 and implementing firewall rules that drop direct external traffic, forcing access through a reverse proxy.

Docker Secret Support

The codebase supports Docker secrets through the _FILE suffix convention. Instead of embedding sensitive values directly in environment variables or image layers, mount secrets as files and reference them via OPEN_NOTEBOOK_PASSWORD_FILE and OPEN_NOTEBOOK_ENCRYPTION_KEY_FILE.

Production Docker Compose configuration:

services:
  open_notebook:
    image: lfnovo/open_notebook:v1-latest
    environment:
      - OPEN_NOTEBOOK_PASSWORD_FILE=/run/secrets/app_password
      - OPEN_NOTEBOOK_ENCRYPTION_KEY_FILE=/run/secrets/encryption_key
    secrets:
      - app_password
      - encryption_key

secrets:
  app_password:
    file: ./secrets/app_password.txt
  encryption_key:
    file: ./secrets/encryption_key.txt

This pattern keeps passwords out of image layers and version control history while allowing the get_secret_from_env utility to load values at runtime.

Known Security Limitations

According to docs/5-CONFIGURATION/security.md, several limitations require operator attention:

  • Clear-text transmission: Passwords travel in Authorization headers without additional hashing, making HTTPS mandatory
  • Memory-only storage: The password resides only in application memory with no persistence mechanism or session management
  • No rate limiting: The API does not implement request throttling, exposing endpoints to brute-force attacks without external protection
  • No audit logging: Authentication events and data access are not logged within the application
  • No RBAC: The single-password model provides no granularity—any authenticated client receives full API access

Organizations requiring these features must implement them at the infrastructure layer using reverse proxies, API gateways, or VPN segmentation.

Summary

  • Password authentication gates all API endpoints via PasswordAuthMiddleware when OPEN_NOTEBOOK_PASSWORD is configured, exempting only health and documentation paths
  • Fernet encryption protects SurrealDB-stored credentials using AES-128-CBC, strictly requiring OPEN_NOTEBOOK_ENCRYPTION_KEY for all cryptographic operations
  • CORS hardening requires setting explicit origins in production rather than accepting the default wildcard configuration
  • Docker secrets prevent sensitive data from appearing in image layers or version control via the _FILE suffix pattern processed by get_secret_from_env
  • Known gaps include the absence of rate limiting, RBAC, and audit logs, necessitating reverse proxy or network-level controls for production safety

Frequently Asked Questions

Does Open Notebook support multi-user authentication or role-based access control?

No. According to docs/5-CONFIGURATION/security.md, the system implements only a single optional password for API access via api/routers/auth.py. There is no built-in RBAC, user accounts, or permission granularity—any client presenting the correct bearer token receives full access. Organizations requiring multi-user support must implement an external authentication layer such as OAuth2 proxy or VPN segmentation.

How are AI provider API keys protected in the database?

All provider credentials undergo Fernet encryption using AES-128-CBC with HMAC-SHA256 authentication before persistence in SurrealDB. The open_notebook/utils/encryption.py module manages this process through the encrypt_secret function, deriving the encryption key from the mandatory OPEN_NOTEBOOK_ENCRYPTION_KEY environment variable. Without this key, the application cannot decrypt existing credentials or encrypt new ones.

Is the default CORS configuration safe for production deployments?

No. The default CORS_ORIGINS="*" setting in api/main.py allows any website to make cross-origin requests to your API instance, potentially enabling malicious web applications to access your data. Production deployments must explicitly set CORS_ORIGINS to the trusted frontend URL, such as https://notebook.example.com. The application logs a startup warning when the wildcard configuration remains active.

What transport layer security measures are required for the password authentication?

HTTPS is mandatory because the password transmits in clear-text within the Authorization: Bearer header. While the encryption key protects data at rest, it does not secure data in transit. Operators must terminate TLS at a reverse proxy (such as Nginx or Traefik) or use cloud load balancers with SSL/TLS certificates to prevent credential interception.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →