22
33import uvicorn
44from dotenv import load_dotenv
5- from fastapi import FastAPI
5+ from fastapi import FastAPI , Request
66from fastapi .middleware .cors import CORSMiddleware
7- from fastapi .responses import FileResponse , HTMLResponse
7+ from fastapi .responses import FileResponse , HTMLResponse , JSONResponse
88from fastapi .staticfiles import StaticFiles
99
1010# Load environment variables from .env file
1111load_dotenv ()
1212
1313app = FastAPI ()
1414
15+ # Read allowed origins from environment; fall back to same-origin only
16+ _allowed_origins = os .getenv ("ALLOWED_ORIGINS" , "" ).split ("," )
17+ _allowed_origins = [o .strip () for o in _allowed_origins if o .strip ()]
18+
1519app .add_middleware (
1620 CORSMiddleware ,
17- allow_origins = [ "*" ] ,
18- allow_methods = ["* " ],
21+ allow_origins = _allowed_origins ,
22+ allow_methods = ["GET " ],
1923 allow_headers = ["*" ],
2024)
2125
@@ -35,20 +39,27 @@ async def serve_index():
3539
3640
3741@app .get ("/config" )
38- async def get_config ():
42+ async def get_config (request : Request ):
43+ # Only serve config to same-origin requests by checking the Referer/Origin
44+ origin = request .headers .get ("origin" ) or ""
45+ referer = request .headers .get ("referer" ) or ""
46+ host = request .headers .get ("host" ) or ""
47+ if origin and not origin .endswith (host ):
48+ return JSONResponse (status_code = 403 , content = {"detail" : "Forbidden" })
49+
3950 config = {
40- "API_URL" : os .getenv ("API_URL" , "API_URL not set " ),
51+ "API_URL" : os .getenv ("API_URL" , "" ),
4152 "REACT_APP_MSAL_AUTH_CLIENTID" : os .getenv (
42- "REACT_APP_MSAL_AUTH_CLIENTID" , "Client ID not set "
53+ "REACT_APP_MSAL_AUTH_CLIENTID" , ""
4354 ),
4455 "REACT_APP_MSAL_AUTH_AUTHORITY" : os .getenv (
45- "REACT_APP_MSAL_AUTH_AUTHORITY" , "Authority not set "
56+ "REACT_APP_MSAL_AUTH_AUTHORITY" , ""
4657 ),
4758 "REACT_APP_MSAL_REDIRECT_URL" : os .getenv (
48- "REACT_APP_MSAL_REDIRECT_URL" , "Redirect URL not set "
59+ "REACT_APP_MSAL_REDIRECT_URL" , ""
4960 ),
5061 "REACT_APP_MSAL_POST_REDIRECT_URL" : os .getenv (
51- "REACT_APP_MSAL_POST_REDIRECT_URL" , "Post Redirect URL not set "
62+ "REACT_APP_MSAL_POST_REDIRECT_URL" , ""
5263 ),
5364 "REACT_APP_WEB_SCOPE" : os .getenv (
5465 "REACT_APP_WEB_SCOPE" , ""
@@ -63,9 +74,12 @@ async def get_config():
6374
6475@app .get ("/{full_path:path}" )
6576async def serve_app (full_path : str ):
66- # First check if file exists in build directory
67- file_path = os .path .join (BUILD_DIR , full_path )
68- if os .path .exists (file_path ):
77+ # Resolve the requested path and ensure it stays within BUILD_DIR
78+ file_path = os .path .realpath (os .path .join (BUILD_DIR , full_path ))
79+ build_dir_real = os .path .realpath (BUILD_DIR )
80+ if not file_path .startswith (build_dir_real + os .sep ) and file_path != build_dir_real :
81+ return FileResponse (INDEX_HTML )
82+ if os .path .isfile (file_path ):
6983 return FileResponse (file_path )
7084 # Otherwise serve index.html for client-side routing
7185 return FileResponse (INDEX_HTML )
0 commit comments