GravitLauncher LaunchServer CVE-2026-54617
CRITICALSeverity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Remote unauthenticated raw HTTP GET (AV:N/AC:L/PR:N/UI:N) yields arbitrary file read (C:H) and, via the exposed JWT signing key, admin token forgery giving full integrity and availability impact (I:H/A:H).
Primary rating from GitHub Advisory.
CVSS VectorGitHub Advisory
Lifecycle Timeline
2DescriptionGitHub Advisory
Summary
An unauthenticated path traversal in the LaunchServer HTTP file server (FileServerHandler) lets any remote actor read any file readable by the LaunchServer process (e.g. ../../../../etc/passwd). This is a generic arbitrary-file-read primitive, so the fix must address the traversal itself, not any specific file.
The readable files include the server's own secrets, which turns this from information disclosure into full compromise: the ECDSA private key that signs access JWTs (.keys/ecdsa_id), the refresh-token salt (.keys/legacySalt), and LaunchServer.json (database credentials). With the signing key an attacker mints a valid access token for any account, including admins. That is a full authentication bypass. Pre-auth, default config, port 9274.
Affected: GravitLauncher LaunchServer ≤ 5.7.11 (the LaunchServer application; the published pro.gravit.launcher:*-api Maven artifacts do not contain the vulnerable code).
Details
In FileServerHandler.channelRead0:
path = Paths.get(IOHelper.getPathFromUrlFragment(uri)).normalize().toString().substring(1); // line 194
File file = base.resolve(path).toFile(); // line 200 - no second normalize()substring(1) blindly strips a leading slash, assuming the request-target always starts with /. Netty's HttpServerCodec accepts a request-target without a leading slash verbatim (decoderResult().isSuccess() == true). For such a target, normalize() cannot collapse the leading .., substring(1) turns ../ into ./ (leaving the remaining ..), and base.resolve(path), which is not re-normalized, resolves outside updatesDir.
file.isHidden() (line 201) is checked only on the final path component, so targets that don't start with a dot (ecdsa_id, rsa_id, legacySalt, LaunchServer.json) are served even with showHiddenFiles=false.
The file server is enabled by default (netty.fileServerEnabled=true) and bound to 0.0.0.0:9274. No auth handler precedes FileServerHandler; WebSocketServerProtocolHandler("/api") forwards non-WebSocket / non-/api requests down to it, so the attack is a plain HTTP GET (no WebSocket).
PoC
Reproduced on a from-source build of v5.7.11 (Netty 4.2.12). Must use a raw socket. curl/browsers/HTTP libraries normalize the path and prepend /, hitting the safe branch (false "not reproducible").
printf 'GET ../../.keys/ecdsa_id HTTP/1.1\r\nHost: x\r\n\r\n' | nc <host> 9274Returns the raw ECDSA private-key bytes. Same for ../../.keys/rsa_id, ../../.keys/legacySalt, ../../LaunchServer.json. %2e%2e/... (no leading slash) also works. Depth-robust arbitrary read: ../../../../../../etc/passwd. Control (confirms the root cause): GET /../../.keys/ecdsa_id (WITH leading slash) → 404. Only the no-leading-slash form escapes.
Impact
Unauthenticated remote read of any file the process can access. What that exposes:
.keys/ecdsa_id: the key that signs access JWTs. With it, an attacker mints a valid token for any account, including admins, so this is a full authentication bypass..keys/legacySalt: lets an attacker forge refresh tokens.LaunchServer.json: database credentials.- Any other file readable by the process (config, logs, system files).
Deployment note: a normalizing L7 reverse proxy (stock nginx location / { proxy_pass ...; }) rejects the no-leading-slash request (400) and collapses leading-slash traversal, blocking the primary vector. But the default bind is 0.0.0.0:9274, so protection relies on firewalling the backend port; L4/TCP proxies (HAProxy TCP, nginx stream, CF Spectrum) and direct exposure remain exploitable.
Suggested fix
- Re-
normalize()afterbase.resolve(path)and verifyresolved.startsWith(base). - Reject request-targets that don't start with
/(400). - Default-bind to
127.0.0.1; store.keysoutsideupdatesDir.
Articles & Coverage 2
AnalysisAI
Arbitrary file read in GravitLauncher LaunchServer ≤ 5.7.11 lets an unauthenticated remote attacker retrieve any file readable by the server process via a path-traversal in the default-enabled HTTP file server on port 9274. Because the exposed files include the ECDSA key that signs access JWTs (.keys/ecdsa_id), the refresh-token salt, and database credentials, the flaw escalates from information disclosure to a full authentication bypass allowing forged admin tokens. Publicly available exploit code exists (a raw-socket PoC in the advisory); the issue is not listed in CISA KEV and no active exploitation is confirmed.
Technical ContextAI
GravitLauncher is an open-source custom Minecraft launcher; its LaunchServer component ships an embedded Netty HTTP/WebSocket server (Netty 4.2.x) whose FileServerHandler serves update files out of updatesDir. The root cause is CWE-22 (Improper Limitation of a Pathname to a Restricted Directory). In FileServerHandler.channelRead0 the code does path = Paths.get(IOHelper.getPathFromUrlFragment(uri)).normalize().toString().substring(1) and then base.resolve(path) with no second normalize() and no startsWith(base) containment check. Netty's HttpServerCodec accepts a request-target without a leading slash as a successful decode, so normalize() cannot collapse a leading '..', substring(1) mangles '../' into './' while leaving the remaining traversal, and base.resolve() escapes updatesDir. The isHidden() check is applied only to the final path component, so non-dot secret files (ecdsa_id, rsa_id, legacySalt, LaunchServer.json) are served even with showHiddenFiles=false. The CPE provided (pkg:maven/pro.gravit.launcher:launchserver-api) points at the Maven API artifact, but the advisory explicitly notes the published *-api artifacts do NOT contain the vulnerable code - the flaw is in the deployed LaunchServer application, so the CPE is a poor match for the actually vulnerable component.
RemediationAI
No vendor-released patched version is identified in the available data - the advisory describes the fix rather than naming a fixed release, so upgrade to the first LaunchServer version above 5.7.11 that incorporates the traversal fix and verify the version against the GitHub advisory GHSA-5g75-477j-2c2f before deploying. The advisory's own suggested code fix is to re-normalize() after base.resolve(path) and enforce resolved.startsWith(base), and to reject any request-target that does not start with '/' (return 400). Until a fixed build is confirmed, the most effective compensating control is to place LaunchServer behind a normalizing L7 reverse proxy such as stock nginx (location / { proxy_pass ...; }), which rejects the no-leading-slash form (400) and collapses leading-slash traversal - note this does NOT help if an L4/TCP proxy (HAProxy TCP, nginx stream, Cloudflare Spectrum) or direct exposure is used. Additionally, firewall or rebind the backend to 127.0.0.1 instead of the default 0.0.0.0:9274 so the port is not directly reachable (side effect: any legitimate direct clients must route through the proxy), and relocate the .keys directory outside updatesDir. Because the ECDSA signing key may already be exposed, treat it as compromised: rotate .keys/ecdsa_id, .keys/rsa_id, the legacySalt, and the database credentials in LaunchServer.json, which will invalidate existing issued tokens.
Oracle Java SE 7 Update 6 and earlier contains multiple sandbox bypass vulnerabilities via the ClassFinder and forName m
Remote code execution in IBM Sterling B2B Integrator, Sterling Integrator, and Tivoli Common Reporting allows unauthenti
Java Runtime Environment sandbox bypass via incorrect image channel verification in 2D component allows remote unauthent
Oracle Java SE JDK/JRE 7 and 6 Update 27 and earlier allows remote code execution with complete system compromise throug
JBoss Seam 2 in Red Hat JBoss EAP 4.3.0 fails to sanitize JBoss Expression Language inputs, allowing remote attackers to
Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 update 4 and earlier, 6 up
Multiple vulnerabilities in Oracle Java 7 before Update 11 allow remote attackers to execute arbitrary code by (1) using
Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 2 and earlier, 6 Up
The WLS Security component in Oracle WebLogic Server 10.3.6.0, 12.1.2.0, 12.1.3.0, and 12.2.1.0 allows remote attackers
Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 7 and earlier allow
Remote unauthenticated attackers can execute arbitrary code on Adobe ColdFusion servers through Java deserialization fla
The ExceptionDelegator component in Apache Struts before 2.2.3.1 interprets parameter values as OGNL expressions during
Same weakness CWE-22 – Path Traversal
View allSame technique Path Traversal
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-5g75-477j-2c2f