mirror of
https://github.com/rustsec/advisory-db.git
synced 2026-09-10 05:38:48 -04:00
rojo: DNS rebinding allows unauthenticated read/write access and local program execution via serve API (#3199)
This commit is contained in:
49
crates/rojo/RUSTSEC-0000-0000.md
Normal file
49
crates/rojo/RUSTSEC-0000-0000.md
Normal file
@@ -0,0 +1,49 @@
|
||||
```toml
|
||||
[advisory]
|
||||
id = "RUSTSEC-0000-0000"
|
||||
package = "rojo"
|
||||
date = "2026-06-02"
|
||||
url = "https://github.com/rojo-rbx/rojo/pull/1270"
|
||||
references = ["https://github.com/rojo-rbx/rojo/commit/ac6941f05483b0875fda52c7664cd42033db7fa2"]
|
||||
categories = ["code-execution", "file-disclosure"]
|
||||
keywords = ["dns-rebinding", "cross-origin", "localhost", "code-injection"]
|
||||
|
||||
[versions]
|
||||
patched = [">= 7.7.0"]
|
||||
```
|
||||
|
||||
# Rojo development server vulnerable to DNS rebinding, allowing unauthenticated read/write access and local program execution
|
||||
|
||||
Rojo's `rojo serve` command starts an unauthenticated HTTP API on localhost
|
||||
(default port 34872) with no `Host` or `Origin` header validation. While
|
||||
direct cross-origin `fetch()` requests from a malicious website are blocked by
|
||||
the browser's default CORS policy, an attacker can use DNS rebinding to bypass
|
||||
this restriction entirely.
|
||||
|
||||
The serve API is a two-way sync protocol. Once a DNS rebind is established, a
|
||||
malicious webpage visited by a developer running `rojo serve` can, without any
|
||||
further user interaction:
|
||||
|
||||
- **Read the full project source:** `GET /api/rojo` returns the session ID,
|
||||
root instance ID, and project name. `GET /api/read/{id}` enumerates the
|
||||
complete instance tree including all script contents, exposing proprietary
|
||||
game logic, configuration, and any secrets embedded in source files.
|
||||
- **Write to project files on disk:** `POST /api/write` pushes changes back
|
||||
through Rojo's sync pipeline, allowing an attacker to inject arbitrary Lua
|
||||
into the developer's project. If the developer then publishes their game,
|
||||
the injected code executes on every player's client — a supply chain attack
|
||||
vector.
|
||||
- **Launch local programs:** `POST /api/open/{id}` calls the OS-level
|
||||
`opener::open()` function, which invokes the platform's default handler
|
||||
(`open` on macOS, `xdg-open` on Linux, `start` on Windows) for the target
|
||||
file.
|
||||
Exploitation requires only that `rojo serve` is running (the standard Roblox
|
||||
development workflow) and that the developer visits an attacker-controlled
|
||||
webpage in any browser on the same machine. The port is a fixed well-known
|
||||
default (34872), there is no authentication, and no user interaction is needed
|
||||
beyond the initial page visit.
|
||||
|
||||
The flaw was corrected in [#1270](https://github.com/rojo-rbx/rojo/pull/1270),
|
||||
which adds `Host`/`Origin` header validation to reject cross-origin requests,
|
||||
gates `/api/open` to loopback clients regardless of validated origin, and emits
|
||||
a warning when the server binds to a non-loopback address.
|
||||
Reference in New Issue
Block a user