Repository navigation
Kervan v0.8.0
Added
-
Password-protected share links. Links can require a password (at
least 6 characters, stored as an Argon2id hash) and the WebUI now sets
the download limit too. Share URLs open a public landing page
(/s/<token>) that shows the file name, size, expiry and remaining
downloads, and asks for the password when one is set. Wrong passwords
count toward the per-address login ban. Scripts can use
/api/v1/share/<token>with anX-Share-Passwordheader. Creating,
revoking and downloading through share links is audited (share.*);
the audit record holds only a short token prefix. -
Audit filters.
/api/v1/audit/eventsand/api/v1/audit/export
acceptfromandto(RFC 3339 orYYYY-MM-DD). The Audit page now
filters by date, event type, status, user and text, pages through
results, shows user, protocol, address and details for each event, and
exports with the same filters. -
MCP tools.
get_user(sign-in restrictions, SSH key fingerprints,
effective policy),list_groupsandverify_audit(checks the
tamper-evident chain).audit_querynow also filters bystatus,
fromandto. The README gains an MCP section. -
Fuzz targets for the SFTP packet handler, SCP sink and exec parser,
the FTP command loop and its path/command parsers (go test -fuzz).
go testruns their seed corpora, including the crashers found so far. -
Interop suite.
make interopruns lftp (FTP, explicit and implicit
FTPS, SFTP), rclone (FTP, FTPS, SFTP) and paramiko against a running
server: 26 checks. -
Docs.
docs/openapi.yaml(OpenAPI 3.1 reference for the REST API),
CONTRIBUTING.md(workflow, architecture map, conventions, release
steps), and an up-to-date.project/ROADMAP.md.
Fixed
- FTPS uploads from lftp (GnuTLS) failed with
426and empty files.
Under TLS 1.3 the server sent session tickets on the data connection that
the client never read, so its close turned into a TCP reset that dropped
the upload. Data connections no longer issue session tickets. - An SFTP write at a huge offset crashed the server when the user's
storage was the memory backend: the backend tried to allocate the whole
gap. The memory backend now refuses gaps over 64 MiB and files over
4 GiB, writes in place instead of copying the file on every write, and
rejects overflowing seeks. - A panic in an SFTP/SCP channel ended the whole process, because the
channel goroutine had no recovery. It now ends only that channel and is
logged. - SFTP packets declaring a large length (up to 16 MiB) were allocated
in full before any data arrived. Buffers above 512 KiB now grow only as
the data actually arrives. - Failed FTP transfers are now logged with the underlying error.
- Admin file actions were audited under the wrong user. When an admin
worked on another user's files through/api/v1/files/{user}/…, the
audit record named the owner as the actor. It now names the admin, with
the owner inmeta.target_user. - The WebSocket ignored sign-in restrictions. It now applies expiry,
allowed addresses and allowed protocols at connect and before every
snapshot, so a disabled or expired account loses its live stream too. - Client-sent
X-Auth-*headers are now stripped before routing. They
were already overwritten on authenticated routes, but public routes could
see them. - Password-hash export (
/api/v1/users/export?include_password_hashes=1)
now requires a signed-in admin session; ausers:readAPI key gets 403.
Every user export is audited (admin.user.export). - Config patches can no longer change fields the config view redacts,
such asstorage.backends.*.options.access_key. - Existence probing. Another user's session or share link now returns
404, like a missing one, instead of 403. Deleting an unknown API key
returns 404 (was 400). An admin naming an unknown user under
/api/v1/files/{user}/gets 404 (was 500). GET /api/v1/server/statusrejects other methods with 405.- Audit export validates its filters before reading the log, and streams
the log, keeping only matching events. A CSV export cut short no longer
tries to write a JSON error after the headers were sent. completed_atis omitted for transfers still in progress (it showed the
zero time).
Changed
- Share-link
share_urlis now the landing page (/s/<token>). The direct
download isdownload_url. Existing/api/v1/share/<token>links keep
working.