Repository navigation
Kervan v0.1.0
Verified end to end against a running server with real clients: OpenSSH
sftp/scp (SFTP and legacy modes), curl (FTP in EPSV/PASV/PORT/EPRT, FTPS
explicit/implicit, SFTP, SCP), a headless browser for the WebUI, and the
Docker image. Those client runs are now part of the test suite
(internal/server/interop_test.go).
Fixed
- SFTP: reverted the v0.0.2 DATA/NAME packet-type swap. The draft and
OpenSSH use DATA=103 and NAME=104; v0.0.2 broke every real client
("Expected SSH2_FXP_NAME(104) packet, got 103") while the wire tests,
which encoded the same misreading, stayed green. - SFTP: SETSTAT/FSETSTAT are implemented (truncate; best-effort
permissions/times). OpenSSH 9+scpfailed every upload with
"remote fsetstat: Operation unsupported". - SFTP: the session sends
exit-status, soscpno longer exits 1 after
a successful transfer. - SSH: authorized_keys entries with a comment or options now match.
Before this, only keys imported throughmigrate ssh-keysworked. - SCP: shell-quoted targets are unquoted, so curl and libssh2 uploads no
longer land in a file literally named'/path'.-psends theTtime
record that libssh2 requires and applies incoming times. Completed
transfers are no longer failed when libssh2 closes without the final ack.
Ambiguous multi-word targets are refused, as OpenSSH does. - store: the JSON store is safe to share between the server and CLI
commands. Writes are locked read-modify-writes of the file, and reads pick
up external changes. Before this, a user created withkervan user create
against a running server could not log in, and the server's next write
silently deleted it. - WebUI: live updates work in browsers. The server rejected the
auth.<token>WebSocket subprotocol that the WebUI (and README) use, so
the dashboard was stuck in snapshot mode. - WebUI: page content now starts at the top of the viewport instead of
one screen height down, and the compact sidebar links are styled again.
A Radix tooltip had stringified NavLink's className callback. - config:
ftps.enabled: falsedisables FTPS even when a certificate is
configured.audit.enabled: falsedisables the audit sinks. - CI: fixed the gofmt and staticcheck failures on master. The
cross-protocol tests use ephemeral ports instead of fixed ones.
Added
- security:
security.allowed_ips/denied_ipsare enforced on FTP,
FTPS, SFTP/SCP and the API, and can be reloaded at runtime.
ftp.max_connections/sftp.max_connectionsare enforced. Over-limit
FTP clients get421and the rejection is audited. - security: a per-address login ban (
ip_ban_threshold,
ip_ban_duration,whitelist_ips) shared by FTP, SFTP and the API, with
IPv6 grouped per /64.brute_force.enablednow also controls account
lockout, and everybrute_force.*key is reloadable. - security:
auth.require_special_charis enforced, CSP (hash-pinned
inline script) and HSTS (on TLS) headers are sent, andftps.client_auth
/client_ca_fileadd client-certificate verification for FTPS. - FTP:
EPSV,PORT/EPRT(withftp.active_modeand bounce
protection),RESTresume forRETR/STOR,CDUP. - ops:
server.pid_fileis written and removed on shutdown, and a
startup warning is logged for settings that have no effect. Session
last_seen_atis updated on activity, accept loops back off on errors,
and the health checkcobaltdbwas renamed tostore. - CI: a
go test -racejob.
Security
- deps: Go toolchain go1.26.2 -> go1.26.8 and x/crypto v0.57.0,
x/net v0.59.0, x/text v0.42.0, x/sys v0.48.0. govulncheck had reported
22 reachable vulnerabilities, including in the SSH stack and in
crypto/tls, crypto/x509 and net/http; it now reports 0. - WebUI deps: react-router 7.18 (the only affected runtime package),
vite and related build tooling, and vitest 5. npm audit had reported 14
advisories (2 critical); it now reports 0.
Changed
- CI: GitHub Actions CI runs only on manual dispatch
(gh workflow run CI). Usemake checklocally for the same checks and
make auditfor vulnerability scans.
Removed
- Build and coverage artifacts that had been committed (
dist/,
kervan.exe, root-level coverage profiles).
Checksums are in checksums.txt. Verify with sha256sum -c --ignore-missing checksums.txt.