How CORS Settings Are Configured in Open Notebook: Security Implications Explained
Open Notebook configures CORS through a single CORS_ORIGINS environment variable parsed at startup in api/main.py, where a default wildcard allows any origin and explicit domains are required for secure production deployments.
Open Notebook is an open-source FastAPI application whose cross-origin resource sharing behavior is governed by a centralized environment variable. Understanding how CORS settings are configured in this project is critical because the default wildcard permits any website to reach the API. This analysis walks through the exact source code in lfnovo/open-notebook to explain the configuration mechanics and their direct security impact.
How CORS Settings Are Configured in Open Notebook
All CORS behavior in Open Notebook is centralized in api/main.py. According to the lfnovo/open-notebook source code, the application reads one environment variable, transforms it into a Python list, and passes that list directly to FastAPI's CORSMiddleware.
Load and Parse the CORS_ORIGINS Variable
When the application boots, dotenv.load_dotenv() reads the process environment or a local .env file, as seen at the top of api/main.py. The helper function _parse_cors_origins then splits the comma-separated string into a Python list. If the value is "*" or the variable is missing entirely, it resolves to ["*"].
The parsed result is stored in CORS_ALLOWED_ORIGINS, and a boolean flag named CORS_IS_DEFAULT_WILDCARD records whether the fallback is active. During startup, the code logs a warning if the wildcard is in effect; otherwise it logs the explicit origins list.
Install CORSMiddleware After Authentication
In api/main.py, CORSMiddleware is added after the authentication middleware so that CORS processing applies to every request. This ordering—visible when comparing the middleware registration in api/main.py with the auth stack in api/auth.py—ensures that pre-flight and actual requests receive headers even on protected routes. The middleware receives allow_origins=CORS_ALLOWED_ORIGINS, allow_credentials=True, allow_methods=["*"], and allow_headers=["*"].
Mirror CORS Headers in Exception Handlers
When an exception fires before the middleware can attach headers, a helper named _cors_headers replicates the middleware's origin-check logic and injects identical CORS headers into the error response. This maintains consistent browser enforcement for failure responses such as 413 Payload Too Large.
Security Implications of Open Notebook CORS Settings
The simplicity of the single-variable design creates distinct security postures depending on deployment choices.
Risks of the Default Wildcard
When CORS_ORIGINS is unset, Open Notebook defaults to ["*"]. This means any website can attempt authenticated fetch or XMLHttpRequest calls to the API. Because the configuration also sets allow_credentials=True, browsers will reject responses that carry both credentials and a wildcard Access-Control-Allow-Origin header. The server still emits the header, which leads to confusing client failures while signaling an insecure configuration.
Explicit Origin Whitelisting
Setting CORS_ORIGINS to an exact domain restricts the Access-Control-Allow-Origin response header to that origin only. This prevents unrelated sites from reading API responses. With allow_credentials=True still enabled, authenticated requests are permitted exclusively from the trusted frontend.
Startup Validation and Runtime Constraints
The _parse_cors_origins parser silently drops empty entries, but a malformed origin—such as one missing the https:// scheme—will be treated as disallowed and trigger browser CORS errors. Additionally, the variable is read once at import time, so changing it requires a full application restart rather than a hot reload.
Practical Configuration Examples
The project includes an .env.example file that shows the CORS_ORIGINS placeholder. Use the patterns below to lock down production deployments.
Setting Allowed Origins in .env
Create or edit the environment file to list trusted frontends exactly.
# .env (or an environment variable set by your container orchestrator)
CORS_ORIGINS=https://notebook.example.com,https://admin.example.com
Running the API with Docker
Pass the origin list directly when starting the container.
docker run -e CORS_ORIGINS="https://notebook.example.com" \
-p 5055:5055 lfnovo/open-notebook:latest
Calling the API from a Trusted Frontend
The following JavaScript expects the requesting page to match an origin listed in CORS_ORIGINS.
fetch('http://localhost:5055/api/notebooks', {
credentials: 'include', // cookies / auth headers are allowed
})
.then(r => r.json())
.then(console.log)
.catch(console.error);
If the caller's domain is absent from the whitelist, the browser blocks the response with a CORS error.
Verifying Headers with curl
An untrusted origin receives no CORS header.
curl -I -H "Origin: https://evil.com" http://localhost:5055/api/notebooks
# No Access-Control-Allow-Origin header → request blocked by browser
A trusted origin receives the reflected header.
curl -I -H "Origin: https://notebook.example.com" http://localhost:5055/api/notebooks
# Access-Control-Allow-Origin: https://notebook.example.com
Summary
- Open Notebook drives all CORS behavior through the
CORS_ORIGINSenvironment variable defined inapi/main.py. - The helper
_parse_cors_originsconverts a comma-separated string intoCORS_ALLOWED_ORIGINS, defaulting to["*"]when the variable is missing. - A default wildcard combined with
allow_credentials=Truecauses browsers to reject credentialed requests and creates a security gap. - Explicit origin whitelisting is required for production to ensure only trusted frontends can read authenticated API responses.
- The
_cors_headershelper preserves CORS policy consistency even on error responses.
Frequently Asked Questions
What happens if I do not set CORS_ORIGINS in Open Notebook?
If the variable is missing, _parse_cors_origins falls back to ["*"]. This allows any website to request the API, but because allow_credentials=True is set, browsers will block cross-origin responses that include authentication material, resulting in broken frontend behavior.
Can I change CORS_ORIGINS without restarting the application?
No. The value is read once at import time in api/main.py. Updating the environment variable requires a rolling restart of the application process or container to take effect.
Why does Open Notebook place CORSMiddleware after authentication middleware?
In the source code, CORSMiddleware is installed after the auth middleware in the FastAPI stack so that CORS processing still runs on every request. This ordering—confirmed by the setup in api/main.py and the definitions in api/auth.py—ensures that protected routes receive proper Access-Control-Allow-Origin headers while maintaining intended security boundaries.
How does Open Notebook handle CORS headers when an API error occurs?
A custom helper called _cors_headers mirrors the CORSMiddleware logic and injects the same headers into error responses. This guarantees that even when exceptions such as 413 Payload Too Large bypass the middleware, the browser still receives the correct origin policy and enforces it.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →