fix: address multiple code audit findings
- CORS: replace wildcard with explicit origin list from CORS_ORIGINS env - Auth: enforce strong defaults, JWT blacklist (RevokedToken model), login rate limiting - Auth: validate password length before bcrypt (72-byte limit) - Scheduler: single-threaded worker to mitigate SQLite write contention - Scheduler: graceful shutdown (wait=True) - Snapshots: add prune_snapshots() with configurable retention count - Storage: isolate localStorage keys via VITE_APP_KEY prefix - Config: add cors_origins, login_rate_limit, snapshot_retention_count settings
This commit is contained in:
+17
-5
@@ -12,7 +12,7 @@ from app.config import get_settings
|
||||
from app.database import init_db
|
||||
from app.models.admin_user import AdminUser
|
||||
from app.database import SessionLocal
|
||||
from app.utils.auth import hash_password
|
||||
from app.utils.auth import hash_password, validate_password_supported
|
||||
from app.services.scheduler import start_scheduler, stop_scheduler
|
||||
from app.routers import auth, upstreams, webhooks, logs, custom_pages, browser_sessions, websites
|
||||
from app.services.browser_session_service import browser_sessions as browser_session_service
|
||||
@@ -21,11 +21,21 @@ logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _init_admin() -> None:
|
||||
def _validate_runtime_settings() -> None:
|
||||
settings = get_settings()
|
||||
if not settings.admin_password:
|
||||
logger.warning("ADMIN_PASSWORD not set, skip admin init")
|
||||
return
|
||||
raise RuntimeError("ADMIN_PASSWORD must be set")
|
||||
if settings.admin_password in {"changeme", "changeme123"}:
|
||||
raise RuntimeError("ADMIN_PASSWORD must not use the default placeholder")
|
||||
if not settings.jwt_secret or settings.jwt_secret == "change-me-in-production":
|
||||
raise RuntimeError("JWT_SECRET must be set to a non-default value")
|
||||
if not settings.cors_origin_list:
|
||||
raise RuntimeError("CORS_ORIGINS must include at least one explicit origin")
|
||||
validate_password_supported(settings.admin_password)
|
||||
|
||||
|
||||
def _init_admin() -> None:
|
||||
settings = get_settings()
|
||||
db = SessionLocal()
|
||||
try:
|
||||
exists = db.query(AdminUser).filter(AdminUser.email == settings.admin_email).first()
|
||||
@@ -45,6 +55,7 @@ def _init_admin() -> None:
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
_validate_runtime_settings()
|
||||
init_db()
|
||||
_init_admin()
|
||||
start_scheduler()
|
||||
@@ -63,9 +74,10 @@ app = FastAPI(
|
||||
openapi_url="/api/openapi.json",
|
||||
)
|
||||
|
||||
settings = get_settings()
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_origins=settings.cors_origin_list,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
|
||||
Reference in New Issue
Block a user