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_ORIGINS from environment variables and parses it via _parse_cors_origins in api/main.py.
  • Wildcard fallback: When unset, defaults to "*" with logged warnings to alert developers of insecure configurations.
  • Permissive middleware: Registers CORSMiddleware with allow_credentials=True, allow_methods=["*"], and allow_headers=["*"].
  • Error handling coverage: Uses the _cors_headers helper 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:

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 →