Problem
mo2-server listens on 127.0.0.1:5000 and exposes endpoints that mutate
the user's machine: archive uploads, batch-script spawns
(deploy.bat, purge.bat), test-runner spawns, config writes, FOMOD JSON
deletes. The HTTP layer currently has no authentication and the CORS rule
is origin("*") (src/main.cpp around the crow::App<crow::CORSHandler>
block).
The loopback bind does not protect against a malicious webpage the user
happens to be browsing in the same session. Any tab can issue
fetch('http://127.0.0.1:5000/api/...'). CORS only governs whether JS can
read the response; the request is already executed by the server, so the
side effect (file write, process spawn, config change) happens regardless.
For "simple" requests like multipart/form-data uploads there is no CORS
preflight at all, so even the read-side block does not fire.
Concretely vulnerable today:
POST /api/installation/upload (multipart, no preflight)
POST /api/installation/install
POST /api/plugin/deploy / purge (spawns batch scripts)
POST /api/test/run (spawns Python)
POST /api/mo2/fomods/scan
POST /api/logs/clear / clear/test
PUT /api/config
DELETE /api/mo2/fomods/<name>
The MO2 Python plugin does not use HTTP (it loads mo2-salma.dll via
ctypes), so the only legitimate HTTP client is the local dashboard.
Problem
mo2-serverlistens on127.0.0.1:5000and exposes endpoints that mutatethe user's machine: archive uploads, batch-script spawns
(
deploy.bat,purge.bat), test-runner spawns, config writes, FOMOD JSONdeletes. The HTTP layer currently has no authentication and the CORS rule
is
origin("*")(src/main.cpparound thecrow::App<crow::CORSHandler>block).
The loopback bind does not protect against a malicious webpage the user
happens to be browsing in the same session. Any tab can issue
fetch('http://127.0.0.1:5000/api/...'). CORS only governs whether JS canread the response; the request is already executed by the server, so the
side effect (file write, process spawn, config change) happens regardless.
For "simple" requests like
multipart/form-datauploads there is no CORSpreflight at all, so even the read-side block does not fire.
Concretely vulnerable today:
POST /api/installation/upload(multipart, no preflight)POST /api/installation/installPOST /api/plugin/deploy/purge(spawns batch scripts)POST /api/test/run(spawns Python)POST /api/mo2/fomods/scanPOST /api/logs/clear/clear/testPUT /api/configDELETE /api/mo2/fomods/<name>The MO2 Python plugin does not use HTTP (it loads
mo2-salma.dllviactypes), so the only legitimate HTTP client is the local dashboard.