How CORS is Configured in the FastAPI Application: Open Notebook's Environment-Driven Approach
The Open Notebook API configures Cross-Origin Resource Sharing (CORS) through FastAPI's CORSMiddleware, dynamically reading allowed origins from the CORS_ORIGINS environment variable and falling back to a permissive wildcard ("*") with security warnings when unset.
The lfnovo/open-notebook repository implements a flexible, security-conscious CORS setup for its FastAPI backend. Located in api/main.py, the configuration parses environment variables at startup to determine which origins can access the API, making it adaptable for both local development and production deployments.
Environment-Driven Origin Configuration
At application startup, the code retrieves the raw CORS origins string from the environment and processes it through a parsing utility.
_cors_origins_raw = os.getenv("CORS_ORIGINS")
CORS_ALLOWED_ORIGINS = _parse_cors_origins(_cors_origins_raw or "*")
CORS_IS_DEFAULT_WILDCARD = _cors_origins_raw is None
(see lines 62‑64 of [api/main.py](https://github.com/lfnovo/open-notebook/blob/main/api/main.py#L62-L64))
The _parse_cors_origins function converts the environment string into a list of allowed origins. When CORS_ORIGINS is undefined, the system defaults to "*", enabling all origins but flagging this as a default configuration for security monitoring.
Middleware Registration in api/main.py
After initializing the password authentication middleware, the application registers FastAPI's built-in CORSMiddleware with the computed origin list.
app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
(see lines 88‑95 of [api/main.py](https://github.com/lfnovo/open-notebook/blob/main/api/main.py#L88-L95))
This configuration explicitly:
- Allows credentials to support cookie-based authentication
- Permits all HTTP methods (
"*") to enable RESTful operations - Accepts all headers (
"*") for content-type flexibility
Security Warnings and Default Behavior
The application includes explicit logging to warn administrators when running with the insecure wildcard default.
if CORS_IS_DEFAULT_WILDCARD:
logger.warning(
"CORS_ORIGINS is not set — API accepts cross‑origin requests from any origin ..."
)
else:
logger.info(f"CORS allowed origins: {CORS_ALLOWED_ORIGINS}")
(see lines 63‑71 of [api/main.py](https://github.com/lfnovo/open-notebook/blob/main/api/main.py#L63-L71))
If CORS_ORIGINS is not set, the API logs a warning indicating it accepts cross-origin requests from any origin. This behavior facilitates local development but requires explicit configuration for production security.
CORS Headers for Error Responses
Beyond the middleware, the application ensures CORS compliance for error responses through a dedicated _cors_headers helper function. This utility constructs proper Access-Control-Allow-* headers for custom exception handlers, ensuring that client browsers receive CORS headers even when the API returns error payloads.
(see lines 67‑88 of [api/main.py](https://github.com/lfnovo/open-notebook/blob/main/api/main.py#L67-L88))
This prevents cross-origin errors from masking actual API error messages, maintaining debuggability while preserving security boundaries.
Practical Configuration Examples
Restrict CORS to specific domains in production:
export CORS_ORIGINS="https://notebook.example.com"
uv run uvicorn api.main:app --reload
For Docker or Docker Compose deployments:
environment:
- CORS_ORIGINS=https://notebook.example.com,https://app.example.com
To inspect the parsed origins at runtime:
import os
from api.main import CORS_ALLOWED_ORIGINS
print("Allowed origins:", CORS_ALLOWED_ORIGINS)
Summary
- Environment-driven configuration: The API reads
CORS_ORIGINSfrom environment variables and parses it via_parse_cors_originsinapi/main.py. - Wildcard fallback: When unset, defaults to
"*"with logged warnings to alert developers of insecure configurations. - Permissive middleware: Registers
CORSMiddlewarewithallow_credentials=True,allow_methods=["*"], andallow_headers=["*"]. - Error handling coverage: Uses the
_cors_headershelper to ensure CORS headers appear on error responses.
Frequently Asked Questions
What happens if CORS_ORIGINS is not set?
The API falls back to a wildcard ("*") allowing all origins and logs a warning message. This facilitates local development but should never be used in production environments where explicit origin restrictions are required.
Can I configure multiple allowed domains?
Yes. The _parse_cors_origins function accepts a comma-separated list or array-formatted string from the CORS_ORIGINS environment variable, converting it into a list of allowed origins for the middleware.
Why are CORS headers needed for error responses?
Standard FastAPI middleware only processes successful responses. The _cors_headers helper ensures custom exception handlers include proper Access-Control-Allow-* headers, preventing browsers from blocking error payload visibility due to CORS policy violations.
Does the CORS configuration allow authentication cookies?
Yes. The middleware explicitly sets allow_credentials=True, which permits browsers to send authenticated requests including cookies and authorization headers to the API.
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 →