The share management endpoints serialized the storage struct directly, returning
the bcrypt password_hash (crackable offline) and the bypass token for every
share an authenticated caller could list, with admins seeing them for all users.
Return a response DTO that exposes only whether a share is password-protected
(hasPassword) and drops both secrets. The storage struct keeps its tags so the
secrets stay persisted and the server-side auth/public flows are unchanged.
Updates the frontend to use hasPassword and adds a regression test.
cleanUsername is many-to-one, so distinct usernames (e.g. "teamone/x" and
"teamone-x") can normalize to the same home directory. With CreateUserDir
enabled, the second registrant silently reused the first user's directory,
breaking per-user isolation. Add a GetByScope lookup and reject a signup whose
derived scope is already taken. The check is gated on CreateUserDir: when it is
off, signups intentionally share the configured default scope. Adds a regression
test for the colliding-username case.
The fix for CVE-2026-54093 rewrote backslashes to the path separator "/" in
archive entry names. On POSIX hosts a backslash is a legal filename byte, so
that rewrite manufactured a traversal sequence ("..\..\x" -> "../../x") out
of a single in-scope file, turning a Windows-only zip-slip into a cross-platform
one. Neutralize backslashes to an inert character instead, and reject any entry
whose name is not already a normalized root-relative path. Adds a regression
test that downloads a folder containing a backslash-named file as a zip.
When Signup is enabled with the default scope and createUserDir off, every
self-registered user inherits the served root and can read/modify/delete all
files. Add a startup WARNING for this configuration and document the risk and
the --createUserDir mitigation. No behavior or default change.
WithinScope compared targets against root+separator, which produced
"//" when the scope resolved to "/". No path matched, so every write
was rejected with os.ErrPermission (HTTP 403), breaking saves and
uploads for root-scoped installs. Skip the appended separator when root
already ends in one.
Check WithinScope for src and dst in resourcePatchHandler before
fileutils.Copy/MoveFile, which follow symlinks and bypassed the
stat()/writeFile() guards (GHSA-239w-m3h6-ch8v).
- http/raw.go: strip Windows backslash separators from archive entry names
on any host. filepath.ToSlash is a no-op for "\" on Linux, so a stored
backslash filename was emitted verbatim and could escape the extraction
directory on Windows extractors (zip-slip). (GHSA-gxjx-7m74-hcq8)
- http/auth.go: cap the login and signup request bodies with
http.MaxBytesReader (1 MiB). The JSON decoder previously read an
arbitrarily large password into memory before bcrypt truncated it,
enabling unauthenticated memory-exhaustion DoS. (GHSA-w5fm-68j4-fpc4)
- files/file.go, http/resource.go: add files.WithinScope and refuse to
follow a symlink whose on-disk target escapes the user's scoped root,
on both the read path (stat) and the write path (writeFile). Prevents a
scoped user from reading/overwriting/sharing files outside their scope
via a pre-existing escaping symlink. (GHSA-239w-m3h6-ch8v)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>