Open Notebook CORS Middleware Security Considerations for Production Deployments
Open Notebook’s FastAPI backend defaults to allowing all origins with credentials enabled, which exposes production APIs to cross-origin attacks unless you explicitly configure the CORS_ORIGINS environment variable to whitelist only trusted domains.
The Open Notebook project relies on Starlette’s CORSMiddleware to handle cross-origin resource sharing in its FastAPI-based API. Understanding the CORS middleware security considerations for production deployments is essential because the default configuration prioritizes local development convenience over security, potentially allowing credential leakage and unauthorized cross-origin requests from malicious websites.
Default Wildcard Origin Risks
Automatic Fallback to Permissive Settings
In api/main.py, the application parses CORS configuration using a local helper function that defaults to the "*" wildcard when the environment variable is unset:
_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
As implemented in api/main.py#L62-L64, this logic sets CORS_ALLOWED_ORIGINS to accept requests from any domain if you do not explicitly define the CORS_ORIGINS environment variable.
Startup Warning Indicators
When CORS_IS_DEFAULT_WILDCARD evaluates to True, the application emits a warning log at startup (api/main.py#L163-L168) alerting administrators that the API accepts cross-origin requests from any origin. This serves as a failsafe to notify operators that the deployment remains in an insecure default state.
Credential Handling Vulnerabilities
Hardcoded Credential Permission
The middleware registration in api/main.py#L191-L194 hardcodes allow_credentials=True:
app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
This configuration instructs browsers to include cookies, HTTP authentication headers, and client-side certificates with cross-origin requests. When combined with wildcard origins or overly permissive origin lists, this allows malicious websites to perform authenticated actions against your API using the victim’s existing session credentials.
Cross-Origin Data Exfiltration
Because the default headers and methods are also set to "*", attackers can read sensitive API responses from any origin that successfully authenticates. The combination of wildcard origins and credential transmission creates a high-risk scenario for data exfiltration and session hijacking.
Middleware Placement and Error Handling
Request Processing Order
The CORS middleware is added last in the application initialization sequence (api/main.py#L188-L195). In FastAPI’s middleware architecture, the last-added middleware processes requests first, ensuring that CORS headers are injected before authentication or routing logic executes. This ordering guarantees that even requests rejected by upstream middleware still receive proper CORS headers.
Exception Handler CORS Injection
The application implements custom exception handlers that manually inject CORS headers into error responses using the _cors_headers(request) utility function (api/main.py#L67-L84 and api/main.py#L98-L105). This prevents browsers from blocking error details due to missing CORS headers on 4xx or 5xx responses, ensuring consistent cross-origin behavior even during failure states.
Production Hardening Configuration
Follow these steps to secure the CORS middleware in production environments:
-
Explicitly define
CORS_ORIGINS– Set this environment variable to a comma-separated list of trusted front-end URLs (e.g.,https://notebook.example.com,https://admin.example.com) instead of relying on the wildcard default. -
Audit credential requirements – Review whether your front-end actually requires cookie-based authentication or HTTP-auth headers. If using token-based authentication in request headers, consider setting
allow_credentials=Falseinapi/main.py#L191. -
Restrict HTTP methods – Replace
"*"with explicit methods your API requires (e.g.,["GET", "POST", "PUT", "DELETE"]) to limit the attack surface for cross-origin state-changing requests. -
Validate startup logs – Confirm that
CORS_IS_DEFAULT_WILDCARDisFalseand verify the parsed whitelist appears correctly in the startup logs emitted atapi/main.py#L163-L168. -
Configure reverse proxy CORS – Ensure your reverse proxy (nginx, Traefik, etc.) forwards or adds appropriate CORS headers for errors generated at the proxy layer (such as 413 Payload Too Large), as the FastAPI CORS middleware only handles application-level responses.
Secure Configuration Example
Environment configuration:
# .env file
CORS_ORIGINS=https://notebook.example.com,https://admin.example.com
Application-level restrictions (modifying api/main.py):
app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ALLOWED_ORIGINS, # Parsed from CORS_ORIGINS above
allow_credentials=True, # Only if cookies/auth headers are required
allow_methods=["GET", "POST", "PUT", "DELETE"], # Explicit method whitelist
allow_headers=["Authorization", "Content-Type"], # Explicit header whitelist
)
Error handling ensures CORS compliance:
@app.exception_handler(StarletteHTTPException)
async def custom_http_exception_handler(request: Request, exc: StarletteHTTPException):
return JSONResponse(
status_code=exc.status_code,
content={"detail": exc.detail},
headers={**(exc.headers or {}), **_cors_headers(request)},
)
Summary
- Open Notebook defaults to
CORS_ORIGINS="*"when the environment variable is unset, exposing the API to any domain. - The hardcoded
allow_credentials=Trueinapi/main.pycreates credential leakage risks when combined with permissive origin settings. - Middleware placement as the last-added middleware ensures CORS headers are present before authentication checks execute.
- Custom exception handlers in
api/main.pymanually inject CORS headers to maintain cross-origin visibility during error responses. - Production security requires explicitly setting
CORS_ORIGINS, auditing credential needs, and restricting methods/headers to minimum required values.
Frequently Asked Questions
What happens if I don't set CORS_ORIGINS in production?
The API falls back to accepting requests from any origin ("*") while still allowing credentials, which allows malicious websites to make authenticated requests using your users' existing session cookies or HTTP-auth headers against the API.
Why is allow_credentials=True considered a security risk?
When allow_credentials=True is combined with wildcard or overly permissive origin lists, browsers will send cookies, authorization headers, and TLS client certificates with cross-origin requests. This enables attackers to perform actions as authenticated users if they can lure victims to a malicious site.
How does the middleware order affect CORS security in Open Notebook?
The CORS middleware is added last in api/main.py, making it the outermost layer in the processing stack. This ensures CORS headers are added to the response before authentication middleware runs, preventing browsers from blocking error responses due to missing CORS headers on rejected requests.
Where is the CORS configuration parsed in the Open Notebook source code?
The configuration is parsed in api/main.py#L62-L64 using os.getenv("CORS_ORIGINS") and the _parse_cors_origins() helper function, with the resulting CORS_ALLOWED_ORIGINS list passed to the CORSMiddleware constructor at api/main.py#L191.
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 →