gonic has arbitrary file write in createPlaylist: any authenticated user can write playlist M3U content to attacker-controlled path on the host
Description
gonic is a music streaming server / free-software subsonic server API implementation. Prior to version 0.21.0, a logic error in ServeCreateOrUpdatePlaylist allows any authenticated Subsonic user (including non-admin) to write playlist M3U content to an attacker-controlled absolute filesystem path on the gonic host, and to create intermediate directories with 0o777 permissions. The bug is independent of CVE-2026-49338 and CVE-2026-49339. It is an unreachable guard clause combined with no path containment in Store.Write. Version 0.21.0 patches the issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Affected products
1Patches
Vulnerability mechanics
Root cause
"Missing input validation: an unreachable guard clause in `ServeCreateOrUpdatePlaylist` bypasses ownership checks, and `Store.Write` does not sanitize `..` sequences in the playlist path."
Attack vector
An authenticated non-admin Subsonic user sends a `createPlaylist` API request with a crafted `id` parameter whose base64-decoded value contains `../` sequences (e.g., `pl -../../../var/log/anything.log`). The unreachable guard causes the owner check to always pass [ref_id=1]. `Store.Write` resolves the traversal via `filepath.Join`, creating the M3U file (and intermediate directories with `0o777` permissions) at an attacker-controlled absolute path [ref_id=1]. The write is M3U-structured but the `name` field is attacker-controlled, enabling overwrite of any file the gonic process can write.
Affected code
`server/ctrlsubsonic/handlers_playlist.go:74-90` contains an unreachable guard clause—`Store.Read` never returns `(non-nil, non-nil-err)`, so the ownership check `playlist.UserID != 0 && playlist.UserID != user.ID` is always bypassed. Additionally, `playlist/playlist.go:146-160` (`Store.Write`) uses `filepath.Join` without any path-containment check, allowing `..` traversal to escape the base directory.
What the fix does
The patch fixes two root causes found in the advisory [ref_id=1]. First, in `handlers_playlist.go:83`, the condition `err != nil && pl != nil` is corrected to `err == nil && pl != nil` so the ownership guard actually executes when a playlist is read successfully. Second, in `playlist/playlist.go`, a path-containment check is added after `filepath.Join`: computing the relative path from `basePath` and rejecting the write if the resolved path escapes the intended playlist directory. The same sanitization should also be applied to `Read()` and `Delete()`. Together these changes prevent both the logic bypass and the directory traversal.
Preconditions
- authValid Subsonic user account (non-admin role is sufficient)
- networkNetwork access to the gonic server's HTTP API
- inputAttacker controls the `id` parameter in a `createPlaylist` request, encoding a directory-traversal payload
Reproduction
See ref_id=1 for a Go test (`TestCreatePlaylistArbitraryWrite_RawPath`) and a curl example that write a file outside the intended playlist directory via a traversal payload.
Generated on Jun 20, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
1- github.com/sentriz/gonic/security/advisories/GHSA-4gxv-p5g5-j7w7mitrex_refsource_CONFIRM
News mentions
0No linked articles in our index yet.