What Changed in v2.1.6
This release turns the old shared clipboard into a full team chat for the web UI and the TUI, and resolves nine coordinated security advisories across the HTTP, WebDAV, SMB, TFTP and collaborator surfaces, plus the usual dependency and CI maintenance.
✨ New Features
-
Team chat (replaces the shared clipboard) — The non-persistent clipboard has grown into a live, collaboration-focused chat, synchronized over the websocket hub across every browser and the
--tuidashboard (which authors astui@<host>). Highlights:- Markdown rendering with the full
:shortcode:emoji catalog (~1800 emoji), composer autosuggest, and collapsible long code blocks. - Emoji reactions (with a who-reacted tooltip) and in-place editing of your own messages (↑ in the composer recalls and cycles them; edits are flagged
(edited)). - Image paste (inlined as base64, or written to disk with
--persist-chat-images) and file upload via 📎 (POST /?chatUpload→.goshs-chat/, respects--read-only, hidden from the listing). - Own-message highlight and opt-in desktop notifications (🔔 toggle) for others' messages when the tab is hidden.
- Opt-in persistence —
--persist-chatwrites the full log (messages, edit flags, per-emoji reaction authors) to<webroot>/.goshs-chat/chat.jsonand restores it on restart; in memory only by default.
# Chat is on by default; persist it across restarts and store pasted images on disk ./goshs --persist-chat --persist-chat-images # Disable the chat entirely ./goshs --no-chat
Flags:
-nc/--no-chat(replaces the old--no-clipboard),-pc/--persist-chat,-pci/--persist-chat-images. - Markdown rendering with the full
🔒 Security
Nine coordinated advisories, all remotely and (by default) unauthenticated.
Content-destruction / mode-flag bypasses under --no-delete / --upload-only / --read-only (#256) — Across every write protocol, --no-delete/--upload-only now treat overwrite, in-place write, truncate and rename/move of a pre-existing file as deletion-class operations and refuse them, while still allowing new-file creation and the operator's own create→write→rename upload flow.
- SMB WRITE opcode overwrite (GHSA-275v-rxgc-4rcj, High) — the SMB2
WRITEopcode ignored the flags, allowing in-place overwrite of existing files. - SMB overwrite disposition & SET_INFO truncate (GHSA-jx6h-2x8x-hf5r, High) —
FILE_OVERWRITE/OVERWRITE_IF/SUPERSEDEcreates andSET_INFOallocation/EOF truncation destroyed existing file contents. - SMB rename/clobber (GHSA-ppvh-3pc7-mvxw, High) —
FileRenameInformationmoved and clobbered existing files. - TFTP
--no-deleteignored (GHSA-2q29-798w-6qcp, High) — a TFTPWRQignored--no-delete, allowing overwrite and truncation of existing files. - TFTP WRQ destroys served files (GHSA-vw29-46p5-7h7x, High) — an unauthenticated
WRQcould truncate any served file (os.CreateimpliesO_TRUNC). - HTTP DELETE on block-listed files (GHSA-ppmc-5w4w-2669, High) — incomplete fix of CVE-2026-40189:
.goshsblock-listed files could still be removed via HTTPDELETE; the block list is now enforced before removal, mirroring the read/share/bulk/WebDAV paths. - WebDAV LOCK plants empty files (GHSA-whqg-vqcj-px54, Medium) — the library's
LOCKhandler plants lock-null empty files for absent paths, bypassing--read-only/--upload-only;webdavGuardnow refusesLOCK/UNLOCKin those modes.
The four SMB sinks now route through SMBServer.protectExisting(), which blocks only when a flag is set and the path is not one the current session just created.
Credential & ACL exposure (#234)
- Collaborator feed leaks the
.goshsAuthorization header (GHSA-wfg4-m42q-9pvq, High) — a legitimate write to a.goshs-protected directory carriesAuthorization: Basic …; the collaborator feed (anonymous when no global-b/-Pis set) still broadcast that header on write paths, leaking per-directory ACL credentials to any watcher. The feed now stripsAuthorization(alongside the CSRF token) unconditionally, at every call site. - Block-only
.goshserases an ancestor's auth (GHSA-cfhc-8j7j-54wq, High) —findEffectiveACLreturned the nearest non-empty.goshs, so a block-only child ({"block":[…]}, noAuth) shadowed and erased a parent directory's auth requirement, yielding unauthenticated reads of the protected subtree. ACLs are now merged up to the webroot: the nearest ancestor that setsAuthwins (a nearer block-only file can never clear it), and block lists are unioned (fail-closed).
🛠️ Build, CI & Packaging
- Migrated the integration test harness dependency (
testcontainers-go0.43 → 0.44). - Star History chart link updated in the README.
⬆️ Dependencies
- Go modules:
github.com/emersion/go-smtp0.24.0 → 0.25.0,github.com/fclairamb/ftpserverlib0.32.1 → 0.32.3,golang.org/x/text0.40.0 → 0.41.0,github.com/moby/go-archive0.2.0 → 0.3.0,github.com/testcontainers/testcontainers-go0.43.0 → 0.44.0. - GitHub Actions:
github/codeql-action(init/autobuild/analyze/upload-sarif) 4.37.3 → 4.37.7,docker/setup-buildx-action4.2.0 → 4.3.0.