[Eclipse Theia] Arbitrary file read via file-download endpoints (no path containment)
Basic information
Project name: Eclipse Theia
Project id: ecd.theia
What are the affected versions?
Confirmed on 1.72.3 and current master (1.73.0). Likely present in all prior releases that ship the same endpoints.
Details of the issue
- CWE-22: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)
- CWE-36: Absolute Path Traversal
- Impact: CWE-200 (Exposure of Sensitive Information)
- Aggravating: CWE-306 (Missing Authentication for Critical Function); see paragraph about authentication, below
The Theia backend exposes HTTP file-download endpoints that convert a client-supplied URI directly to a filesystem path and stream the file, without any restriction to the workspace (or any allow-listed root). A client can therefore read any file readable by the backend process, including files entirely outside the opened workspace (e.g. /etc/hosts, SSH keys, tokens, other users' files on a shared/hosted deployment).
- Standalone
GET /fileendpoint:packages/filesystem/src/node/download/file-download-endpoint.ts(handler registered viaapp.get('/file', ...)):
const uri = url.parse(request.url).query; // client-controlled
const fsPath = FileUri.fsPath(decodeURIComponent(uri));
response.sendFile(fsPath); // no containment check/files/single-file handler:packages/filesystem/src/node/download/file-download-handler.ts(SingleFileDownloadHandler.handle):
const uri = new URI(query.uri).toString(true); // client-controlled
const filePath = FileUri.fsPath(uri);
// fs.stat(filePath) + stream; directories are tar-archived
// no check that filePath is inside a workspace/allowed rootNeither path is normalized against or confined to the workspace roots.
In browser deployments, the connection token is enforced only on WebSocket upgrades. The corresponding Express middleware (packages/core/src/node/hosting/browser-connection-token.ts, BrowserConnectionTokenBackendContribution.expressMiddleware) does not reject tokenless HTTP requests; it only (re)issues the cookie and calls next(). Consequently, these HTTP endpoints are reachable without a valid token. (Electron uses a separate ElectronSecurityToken.)
Steps to reproduce
With the browser example (or any Theia-based app) running, in a terminal on your host system do:
$ curl 'http://<host>:3000/file?file%3A%2F%2F%2Fetc%2Fhosts'This then returns the server's /etc/hosts, a file outside any workspace that any connected frontend has open.
Do you know any mitigations of the issue?
Excluding the @theia/filesystem package from the Theia-based application would not cause the affected service endpoint not to be present at run-time.