# Windows ML CLI: CORS misconfig enables localhost RCE

winml-cli's localhost HTTP API sets allow_origins=* and passes trust_remote_code through, letting any website trigger RCE via a malicious model repo.

- Payout: Research
- Severity: high
- Program: winml-cli
- Found by: Salty43, slvignesh05
- Disclosed: 2026-09-08
- CVE: CVE-2026-84452
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-96p9-rh4f-92cf
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-96p9-rh4f-92cf
- Tags: area:ai domain:ai domain:web impact:rce kind:research platform:ghsa sev:high tech:python technique:source-review vuln:cors vuln:misconfiguration vuln:rce

**Target:** Local FastAPI CLI bridge (serve/cli_api.py) on 127.0.0.1:8000
**Root cause:** The HTTP bridge exposes all CLI commands unauthenticated with allow_origins=["*"] (cli_api.py:150, app.py:219), and build/config pass a JSON trust_remote_code:true unfiltered into AutoConfig.from_pretrained(..., trust_remote_code=True), which imports attacker Python.
**Steps:**
1. Start server: `python -m uvicorn winml.modelkit.serve.cli_api:app --host 127.0.0.1 --port 8000`
2. Create hostile repo with `config.json` containing `{"model_type":"pwn","auto_map":{"AutoConfig":"configuration_pwn.PwnConfig"}}` and `configuration_pwn.py` with module-level payload code
3. From any web page, POST to `http://127.0.0.1:8000/v1/cli/build` with `Origin: https://evil.example` and body `{"args":{"model":"/tmp/poc/evil/pwn","output_dir":"/tmp/poc/out","trust_remote_code":true}}`
4. Response returns `access-control-allow-origin: *`; payload file written proving code execution as server user
**How found:** Noted the loopback bind is defensible alone, but allow_origins=["*"] erases that boundary since the victim's browser is a local process; then traced the JSON trust_remote_code:true through to AutoConfig.from_pretrained(..., trust_remote_code=True) at _autoconfig.py:191 where transformers imports repo Python.
**Exploitation:** Victim loads an attacker page; page JS issues a cross-origin POST to the loopback API (wildcard CORS permits reading the reply). The build command loads the attacker model repo with trust_remote_code, importing configuration_pwn.py whose module-level code runs immediately as the server user, regardless of the command's exit_code.
**Insight:** Localhost dev servers with wildcard CORS turn any browser into an authenticated client; check whether CLI flags like trust_remote_code are passable as JSON booleans through HTTP bridges to reach import-time code execution.

