Skip to main content

GravitLauncher LaunchServer CVE-2026-54617

CRITICAL
Path Traversal (CWE-22)
2026-07-02 https://github.com/GravitLauncher/Launcher GHSA-5g75-477j-2c2f
9.8
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
9.8 CRITICAL
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
vuln.today AI
9.8 CRITICAL

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).

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

2
Analysis Generated
Jul 02, 2026 - 21:23 vuln.today
CVE Published
Jul 02, 2026 - 20:49 github-advisory
CRITICAL 9.8

DescriptionGitHub 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:

java
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> 9274

Returns 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

  1. Re-normalize() after base.resolve(path) and verify resolved.startsWith(base).
  2. Reject request-targets that don't start with / (400).
  3. Default-bind to 127.0.0.1; store .keys outside updatesDir.

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.

More in Java

View all
CVE-2012-4681 CRITICAL POC
9.8 Aug 28

Oracle Java SE 7 Update 6 and earlier contains multiple sandbox bypass vulnerabilities via the ClassFinder and forName m

CVE-2015-7450 CRITICAL POC
9.8 Jan 02

Remote code execution in IBM Sterling B2B Integrator, Sterling Integrator, and Tivoli Common Reporting allows unauthenti

CVE-2013-2465 CRITICAL POC
9.8 Jun 18

Java Runtime Environment sandbox bypass via incorrect image channel verification in 2D component allows remote unauthent

CVE-2011-3544 CRITICAL POC
9.8 Oct 19

Oracle Java SE JDK/JRE 7 and 6 Update 27 and earlier allows remote code execution with complete system compromise throug

CVE-2010-1871 HIGH POC
8.8 Aug 05

JBoss Seam 2 in Red Hat JBoss EAP 4.3.0 fails to sanitize JBoss Expression Language inputs, allowing remote attackers to

CVE-2012-1723 CRITICAL POC
9.8 Jun 16

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 update 4 and earlier, 6 up

CVE-2013-0422 CRITICAL POC
9.8 Jan 10

Multiple vulnerabilities in Oracle Java 7 before Update 11 allow remote attackers to execute arbitrary code by (1) using

CVE-2012-0507 CRITICAL POC
9.8 Jun 07

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 2 and earlier, 6 Up

CVE-2015-4852 CRITICAL POC
9.8 Nov 18

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

CVE-2012-5076 CRITICAL POC
9.8 Oct 16

Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 7 and earlier allow

CVE-2017-3066 CRITICAL POC
9.8 Apr 27

Remote unauthenticated attackers can execute arbitrary code on Adobe ColdFusion servers through Java deserialization fla

CVE-2012-0391 CRITICAL POC
9.8 Jan 08

The ExceptionDelegator component in Apache Struts before 2.2.3.1 interprets parameter values as OGNL expressions during

Share

CVE-2026-54617 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy