FIX: 11 bugs bảo mật/ổn định (static mount chặn dotfile, delete traversal, cleanup giữ clips serverFileId, upload whitelist, password strength, auth audio endpoints, pedalboard==0.9.19, vendor CDN local) + FEATURE: Carla bridge preview/export MIDI notes âm VSTi (POST /midi-render, /carla-play-notes, nút Preview VSTi/Export MIDI->Audio; pedalboard 0.9.19 raw MIDI bytes; SONICFORGE_STORAGE_DIR cô lập test storage)

This commit is contained in:
2026-08-10 18:46:54 +07:00
parent 67ad2b8e4b
commit 61cb4b846f
33 changed files with 1097 additions and 103 deletions
+17 -2
View File
@@ -1,7 +1,7 @@
import os
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
@@ -58,7 +58,22 @@ app.add_middleware(
)
# Mount storage directory (must come before general /static mount)
app.mount("/static/audio", StaticFiles(directory=settings.STORAGE_DIR), name="audio")
# Bug #1: trước đây mount TOÀN BỘ STORAGE_DIR tại /static/audio — StaticFiles
# serve cả dotfile → attacker đọc .secret_key (forge admin token) + sonicforge.db
# (mọi user/hash) + temp/autosave.json mà KHÔNG cần auth. Fix: mount riêng từng
# thư mục con + chặn dotfile bằng SafeStaticFiles.
class SafeStaticFiles(StaticFiles):
"""StaticFiles chặn mọi đường dẫn chứa dotfile/.. (404 thay vì serve)."""
async def get_response(self, path: str, scope):
parts = path.split("/")
if any(p.startswith(".") or p in ("", "..") for p in parts):
raise HTTPException(status_code=404, detail="Not Found")
return await super().get_response(path, scope)
app.mount("/static/audio/uploads", SafeStaticFiles(directory=settings.UPLOADS_DIR), name="uploads")
app.mount("/static/audio/processed", SafeStaticFiles(directory=settings.PROCESSED_DIR), name="processed")
# Mount app static files (js, css)
# Dùng settings.APP_DIR (freeze-aware) thay vì os.path.dirname(__file__):
# khi PyInstaller onefile, __file__ trỏ vào thư mục giải nén tạm _MEI...