diff --git a/crates/rojo/RUSTSEC-0000-0000.md b/crates/rojo/RUSTSEC-0000-0000.md new file mode 100644 index 000000000..7bfc3ce25 --- /dev/null +++ b/crates/rojo/RUSTSEC-0000-0000.md @@ -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.