# Ray is vulnerable to Critical RCE via Safari & Firefox Browsers through DNS Rebinding Attack

Ray dashboard's browser defense only checks User-Agent starts with 'Mozilla'; Firefox/Safari fetch can override it, so DNS rebinding yields unauthenticated RCE via /api/jobs.

- Payout: Research
- Severity: critical
- Program: Ray
- Found by: JLLeitschuh, avilum
- Disclosed: 2025-11-26
- CVE: CVE-2025-62593
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-q279-jhrf-cc6v
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-q279-jhrf-cc6v
- Tags: area:cloud domain:infra domain:web impact:internal-access impact:rce kind:research platform:ghsa sev:critical tech:python technique:chained vuln:auth-bypass vuln:csrf vuln:rce

**Target:** Ray dashboard HTTP API (/api/jobs, /api/job_agent/jobs/) on port 8265
**Root cause:** Browser-request mitigation relies on User-Agent starting with 'Mozilla', but Firefox/Safari fetch permits setting User-Agent, so the guard is bypassable; endpoints have no authentication.
**Steps:**
1. Launch Ray head node: `ray start --head --port=6379`, dashboard on 8265
2. Deploy internet-facing nccgroup/singularity DNS rebinding server
3. Victim on Firefox/Safari visits `http://[singularity]:8265/manager.html`
4. Select 'Ray Jobs RCE (default port 8265)' payload and start attack; retry until rebinding succeeds
5. Payload POSTs to `/api/jobs/` with header `User-Agent: Other` and body containing `entrypoint` shell command
6. Ray executes entrypoint, popping calculator as proof
**How found:** Noticed the browser defense was a weak User-Agent heuristic; hypothesized fetch spec allows UA override in Firefox/Safari (Chrome exempt due to a spec-diverging bug), then combined with DNS rebinding tooling to build full PoC.
**Exploitation:** Attacker lures developer to malicious page; DNS rebinding makes the browser treat the attacker origin as resolving to 127.0.0.1:8265. JS fetch sets `User-Agent: Other` to evade the Mozilla check, then POSTs a job with arbitrary `entrypoint` to /api/jobs/, achieving shell execution on the dev machine. Also usable as confused deputy against network-adjacent Ray instances.
**Escalation:** Browser used as confused deputy to reach private-network Ray instances from an external attacker page.
**Insight:** When a service 'blocks browsers' via User-Agent heuristics, test whether the target browser's fetch allows overriding User-Agent (Firefox/Safari do; Chrome doesn't) and pair with DNS rebinding to reach localhost-only unauthenticated APIs.

## Proof of concept (copied exactly from the original report)

**Vulnerable is_browser_request User-Agent check**

```
def is_browser_request(req: Request) -> bool:
    """Checks if a request is made by a browser like user agent.

    This heuristic is very weak, but hard for a browser to bypass- eg,
    fetch/xhr and friends cannot alter the user-agent, but requests made with
    an http library can stumble into this if they choose to user a browser like
    user agent.
    """
    return req.headers["User-Agent"].startswith("Mozilla")
```

