CVE-2026-54617
GravitLauncher: Unauthenticated path traversal in LaunchServer FileServerHandler
GravitLauncher is an open-source Minecraft launcher based on sashok724's v3. Prior to 5.7.12, an unauthenticated remote actor can send a raw HTTP request target without a leading slash to the default LaunchServer file server on port 9274. FileServerHandler.channelRead0 in components/launchserver/src/main/java/pro/gravit/launchserver/socket/handlers/fileserver/FileServerHandler.java strips the first request-target character and resolves the remaining path against updatesDir without re-normalizing and verifying containment. This leaves parent-directory components in a no-leading-slash request and allows reading any file accessible to the LaunchServer process, including .keys/ecdsa_id, .keys/legacySalt, and LaunchServer.json. Disclosure of those files can expose signing keys, refresh-token material, and database credentials, enabling forged administrative access tokens and full authentication bypass. A normalizing L7 proxy may block the primary request form, but direct exposure and L4/TCP proxies remain affected, and netty.fileServerEnabled is enabled by default. This issue is fixed in 5.7.12.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
9.8
GravitLauncher: Unauthenticated path traversal in LaunchServer FileServerHandler
GravitLauncher is an open-source Minecraft launcher based on sashok724's v3. Prior to 5.7.12, an unauthenticated remote actor can send a raw HTTP request target without a leading slash to the default LaunchServer file server on port 9274. FileServerHandler.channelRead0 in components/launchserver/src/main/java/pro/gravit/launchserver/socket/handlers/fileserver/FileServerHandler.java strips the first request-target character and resolves the remaining path against updatesDir without re-normalizing and verifying containment. This leaves parent-directory components in a no-leading-slash request and allows reading any file accessible to the LaunchServer process, including .keys/ecdsa_id, .keys/legacySalt, and LaunchServer.json. Disclosure of those files can expose signing keys, refresh-token material, and database credentials, enabling forged administrative access tokens and full authentication bypass. A normalizing L7 proxy may block the primary request form, but direct exposure and L4/TCP proxies remain affected, and netty.fileServerEnabled is enabled by default. This issue is fixed in 5.7.12.
- Record
CVE-2026-54617- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-22, CWE-200, CWE-522
- Updated
- 2026-11-02
EUVDEUVD-2026-82391
9.8
GravitLauncher is an open-source Minecraft launcher based on sashok724's v3. Prior to 5.7.12, an unauthenticated remote actor can send a raw HTTP request target without a leading slash to the default LaunchServer file server on port 9274. FileServerHandler.channelRead0 in components/launchserver/src/main/java/pro/gravit/launchserver/socket/handlers/fileserver/FileServerHandler.java strips the first request-target character and resolves the remaining path against updatesDir without re-normalizing and verifying containment. This leaves parent-directory components in a no-leading-slash request and allows reading any file accessible to the LaunchServer process, including .keys/ecdsa_id, .keys/legacySalt, and LaunchServer.json. Disclosure of those files can expose signing keys, refresh-token material, and database credentials, enabling forged administrative access tokens and full authentication bypass. A normalizing L7 proxy may block the primary request form, but direct exposure and L4/TCP proxies remain affected, and netty.fileServerEnabled is enabled by default. This issue is fixed in 5.7.12.
- Record
EUVD-2026-82391- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-5g75-477j-2c2f
9.8
LaunchServer FileServerHandler has an unauthenticated path traversal issue
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> 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
- 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.
- Record
GHSA-5g75-477j-2c2f- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-22, CWE-200, CWE-522
- Updated
- 2026-11-02
NVD
9.8
GravitLauncher is an open-source Minecraft launcher based on sashok724's v3. Prior to 5.7.12, an unauthenticated remote actor can send a raw HTTP request target without a leading slash to the default LaunchServer file server on port 9274. FileServerHandler.channelRead0 in components/launchserver/src/main/java/pro/gravit/launchserver/socket/handlers/fileserver/FileServerHandler.java strips the first request-target character and resolves the remaining path against updatesDir without re-normalizing and verifying containment. This leaves parent-directory components in a no-leading-slash request and allows reading any file accessible to the LaunchServer process, including .keys/ecdsa_id, .keys/legacySalt, and LaunchServer.json. Disclosure of those files can expose signing keys, refresh-token material, and database credentials, enabling forged administrative access tokens and full authentication bypass. A normalizing L7 proxy may block the primary request form, but direct exposure and L4/TCP proxies remain affected, and netty.fileServerEnabled is enabled by default. This issue is fixed in 5.7.12.
- Record
CVE-2026-54617- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-22, CWE-200, CWE-522
- Updated
- 2026-11-02
OSV
9.8
GravitLauncher: Unauthenticated path traversal in LaunchServer FileServerHandler
GravitLauncher is an open-source Minecraft launcher based on sashok724's v3. Prior to 5.7.12, an unauthenticated remote actor can send a raw HTTP request target without a leading slash to the default LaunchServer file server on port 9274. FileServerHandler.channelRead0 in components/launchserver/src/main/java/pro/gravit/launchserver/socket/handlers/fileserver/FileServerHandler.java strips the first request-target character and resolves the remaining path against updatesDir without re-normalizing and verifying containment. This leaves parent-directory components in a no-leading-slash request and allows reading any file accessible to the LaunchServer process, including .keys/ecdsa_id, .keys/legacySalt, and LaunchServer.json. Disclosure of those files can expose signing keys, refresh-token material, and database credentials, enabling forged administrative access tokens and full authentication bypass. A normalizing L7 proxy may block the primary request form, but direct exposure and L4/TCP proxies remain affected, and netty.fileServerEnabled is enabled by default. This issue is fixed in 5.7.12.
- Record
CVE-2026-54617- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-200, CWE-22, CWE-522
- Updated
- 2026-11-02
OSVGHSA-5g75-477j-2c2f
9.8
LaunchServer FileServerHandler has an unauthenticated path traversal issue
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> 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
- 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.
- Record
GHSA-5g75-477j-2c2f- CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-200, CWE-22, CWE-522
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
pro.gravit.launcher:launchserver-apiMaven |
through 5.7.11 | None known |
pro.gravit.launcher:launchserver-apiMaven |
through 5.7.11, plus listed versions 5.0.105.0.65.0.75.0.85.1.0 Show 38 moreShow less5.1.105.1.65.1.85.1.95.2.05.2.15.2.105.2.115.2.125.2.135.2.25.2.35.2.55.2.65.2.75.2.85.2.95.3.05.3.15.3.25.3.35.3.55.3.65.4.05.4.35.4.45.5.05.5.15.5.25.5.35.5.45.6.05.6.15.6.25.6.35.6.75.6.85.6.9 |
None known |
Public exploits
Links only. Every CVE stores no exploit code.
| Source | Link | Date |
|---|---|---|
| Nuclei | GravitLauncher LaunchServer <=5.7.11 - Unauthenticated Path Traversal to Arbitrary File Read |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, Nuclei, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-54617 is a critical vulnerability (CVSS 9.8) in Gravitlauncher Launcher, published July 2, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 3.46%, the 89th percentile. No source names a fixed version.
References
github.com/GravitLauncher/Launcher/security/advisories/GHSA-5g75-477j-2c2f
github.com/GravitLauncher/Launcher/commit/8114a1d4cfbcaab4c1c337d921597805d71dee3b
github.com/GravitLauncher/Launcher/releases/tag/v5.7.12
github.com/advisories/GHSA-5g75-477j-2c2f
github.com/CVEProject/cvelistV5/tree/main/cves/2026/54xxx/CVE-2026-54617.json
nvd.nist.gov/vuln/detail/CVE-2026-54617
github.com/GravitLauncher/Launcher