You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,12 +17,12 @@ A lightweight terminal chat with real-time messaging over WebSockets, optional E
17
17
18
18
### v0.11.0-beta.3 (Current)
19
19
20
-
**Released 2026-04-09.** Changes since **[v0.11.0-beta.2](https://github.com/Cod-e-Codes/marchat/releases/tag/v0.11.0-beta.2)** — compare on GitHub: [`v0.11.0-beta.2...v0.11.0-beta.3`](https://github.com/Cod-e-Codes/marchat/compare/v0.11.0-beta.2...v0.11.0-beta.3). For the commit list (newest-first): **`git log v0.11.0-beta.2..v0.11.0-beta.3 --oneline`** (append **`--reverse`** for oldest-first).
20
+
**Released 2026-04-09.** Changes since **[v0.11.0-beta.2](https://github.com/Cod-e-Codes/marchat/releases/tag/v0.11.0-beta.2)**; compare on GitHub: [`v0.11.0-beta.2...v0.11.0-beta.3`](https://github.com/Cod-e-Codes/marchat/compare/v0.11.0-beta.2...v0.11.0-beta.3). For the commit list (newest-first): **`git log v0.11.0-beta.2..v0.11.0-beta.3 --oneline`** (append **`--reverse`** for oldest-first).
21
21
22
22
#### Client and configuration
23
23
-**Profiles**: Dedupe display names on load; default **Profile-N** naming when adding profiles.
24
24
-**Paths**: **`GetConfigPath`** honors **`MARCHAT_CONFIG_DIR`** (same resolution idea as **`ResolveClientConfigDir()`**).
25
-
-**Keystore**: Portable **v3** format (random salt in file header); legacy path-based PBKDF2 salt migrates on unlock—see **ARCHITECTURE.md** / **PROTOCOL.md** (very old clients may need a current build to read migrated files).
25
+
-**Keystore**: Portable **v3** format (random salt in file header); legacy path-based PBKDF2 salt migrates on unlock; see **ARCHITECTURE.md** / **PROTOCOL.md** (very old clients may need a current build to read migrated files).
26
26
-**Keystore location**: **`GetKeystorePath`** prefers the resolved config directory and the standard per-user **`keystore.dat`** before legacy **`./keystore.dat`** in the process working directory, so a stray file in a git clone does not override your real profile key (**README.md** → Client vs server config; **ARCHITECTURE.md**).
27
27
-**Hardening**: Broader client UX and crypto-path fixes alongside server send-path hardening (see commit **`5feb098`** on `main`).
28
28
@@ -48,7 +48,7 @@ A lightweight terminal chat with real-time messaging over WebSockets, optional E
48
48
-**Scripts**: **`build-release.ps1`** includes a **darwin/arm64** build target.
49
49
50
50
#### Toolchain and security
51
-
-**Go 1.25.9** in **`go.mod`**, GitHub Actions, and the **Docker** builder image—cleans **govulncheck**-listed standard-library issues for**Go 1.25.8** (**crypto/tls**, **crypto/x509**, **archive/tar**, **html/template**, etc.). See **SECURITY.md** for scanner notes (including package-level **pgx**advisories with no fixed release yet; no reachable symbols reported by default **`govulncheck ./...`**).
51
+
-**Go 1.25.9** in **`go.mod`**, GitHub Actions, and the **Docker** builder image clears **govulncheck**-listed standard-library issues from**Go 1.25.8** (**crypto/tls**, **crypto/x509**, **archive/tar**, **html/template**, etc.). See **SECURITY.md** for scanner notes: container/SBOM scans often flag dependency **presence** in the image/binary; **`govulncheck ./...`** checks **reachability**. Package-level **pgx**findings (for example **CVE-2026-33815** / **CVE-2026-33816**) may persist while advisory **fixed-version** metadata lags; marchat ships **pgx** v5.9.0+ with related upstream protocol fixes, and default **`govulncheck ./...`** reports no reachable vulnerable call paths.
52
52
53
53
### v0.11.0-beta.2
54
54
-**Go 1.25.8** across CI, Docker, and docs; **SECURITY.md** updates (supported versions, edwards25519 note)
@@ -594,7 +594,7 @@ E2E encryption enabled with keystore: config/keystore.dat
594
594
### Keystore file format and `MARCHAT_GLOBAL_E2E_KEY`
595
595
596
596
-**On-disk format (current)**: `keystore.dat` is a small binary file: a fixed **magic** and **version**, a **random 16-byte salt** stored in the file, then **AES-GCM** ciphertext of the JSON payload (including the global ChaCha20-Poly1305 key). The passphrase is stretched with **PBKDF2** (SHA-256, 100k iterations) using that embedded salt. This means the same passphrase unlocks the file even if the absolute path to `keystore.dat` changes (for example after moving the file or when the client resolves a different config directory). Older files that derived PBKDF2 salt from the **keystore path** are still supported: on first successful unlock they are **rewritten** in the new format.
597
-
-**Environment variable vs file**: If **`MARCHAT_GLOBAL_E2E_KEY`** is set in the client process, that key is used for encryption/decryption for **this run**. The on-disk keystore is **not** modified. You will see **`[INFO] Using global E2E key from environment variable`**. If you later **unset** the variable, the client uses the key from `keystore.dat` again—so the effective key can appear to “change back” even though the file was never updated. To persist a shared key in the file, run **without** the env var once. When the client **auto-generates** a key, it **does not** print the raw base64 material (only a Key ID); share the key with other clients by copying **`keystore.dat`** and the **same passphrase**, or by agreeing on **`MARCHAT_GLOBAL_E2E_KEY`** beforehand (e.g. **`openssl rand -base64 32`** on a trusted machine).
597
+
-**Environment variable vs file**: If **`MARCHAT_GLOBAL_E2E_KEY`** is set in the client process, that key is used for encryption/decryption for **this run**. The on-disk keystore is **not** modified. You will see **`[INFO] Using global E2E key from environment variable`**. If you later **unset** the variable, the client uses the key from `keystore.dat` again, so the effective key can appear to “change back” even though the file was never updated. To persist a shared key in the file, run **without** the env var once. When the client **auto-generates** a key, it **does not** print the raw base64 material (only a Key ID); share the key with other clients by copying **`keystore.dat`** and the **same passphrase**, or by agreeing on **`MARCHAT_GLOBAL_E2E_KEY`** beforehand (e.g. **`openssl rand -base64 32`** on a trusted machine).
598
598
-**Which file is used**: Same resolution order as in **Client vs server config locations** above (primary config dir → per-user marchat keystore when override is empty → cwd legacy).
599
599
-**Legacy note**: Keystore wrapping was previously upgraded to PBKDF2 (replacing an older derivation). Very old keystores from that era may still need re-initialization if they cannot be decrypted.
600
600
@@ -746,8 +746,8 @@ Profiles stored in platform-appropriate locations:
746
746
747
747
| Issue | Solution |
748
748
|-------|----------|
749
-
| Wrong config folder / paths | Run `./marchat-client -doctor` or `./marchat-server -doctor` (add `-doctor-json` for scripts; set `NO_COLOR` for plain text). See **Client vs server config locations**. **Server:** if you set `MARCHAT_CONFIG_DIR` only in `config/.env`, restart after saving—the loader re-reads it after `Overload`. |
750
-
| Connection failed | Use `ws://` or `wss://` and the path your server uses (default HTTP handler is **`/ws`**—e.g. `ws://host:8080/ws`). |
749
+
| Wrong config folder / paths | Run `./marchat-client -doctor` or `./marchat-server -doctor` (add `-doctor-json` for scripts; set `NO_COLOR` for plain text). See **Client vs server config locations**. **Server:** if you set `MARCHAT_CONFIG_DIR` only in `config/.env`, restart after saving; the loader re-reads it after `Overload`. |
750
+
| Connection failed | Use `ws://` or `wss://` and the path your server uses (default HTTP handler is **`/ws`**, e.g. `ws://host:8080/ws`). |
751
751
|`wss://localhost:8443` reconnect loop / connection refused | Ensure Caddy (or your proxy) is up: `docker compose -f docker-compose.proxy.yml up -d`, or connect directly with `ws://127.0.0.1:8080/ws` ([reverse proxy guide](deploy/CADDY-REVERSE-PROXY.md)). |
752
752
| Admin commands not working | Client must use **`--admin`** and **`--admin-key`** matching the server’s `MARCHAT_ADMIN_KEY`; username must be listed in `MARCHAT_USERS`. |
753
753
| Clipboard issues (Linux) | Install a clipboard tool (e.g. `sudo apt install xclip` or `xsel`). |
@@ -762,7 +762,7 @@ Profiles stored in platform-appropriate locations:
762
762
| Plugin installation fails | Check registry URL (`MARCHAT_PLUGIN_REGISTRY_URL`), network access, and JSON validity; commercial plugins need a valid license for the **plugin name** (see **PLUGIN_ECOSYSTEM.md**). |
763
763
| E2E encryption errors | Use **`--e2e`** and the keystore passphrase; see **[E2E Encryption](#e2e-encryption)** (keystore path, `MARCHAT_GLOBAL_E2E_KEY` vs file). Client and server must share the same global key material. |
764
764
| Global E2E key errors | Key must be **base64** encoding **32 raw bytes** (`openssl rand -base64 32`). **`MARCHAT_GLOBAL_E2E_KEY`** overrides the in-memory key for that process and is **not** written to the keystore file. |
765
-
|`:savefile` picks the wrong payload when names collide | Received files are stored per sender internally, but `:savefile <name>` matches **basename only**. If two users sent the same filename, which copy is saved is **not deterministic**—ask for distinct names or avoid duplicate basenames until disambiguation is exposed in the UI. |
765
+
|`:savefile` picks the wrong payload when names collide | Received files are stored per sender internally, but `:savefile <name>` matches **basename only**. If two users sent the same filename, which copy is saved is **not deterministic**; ask for distinct names or avoid duplicate basenames until disambiguation is exposed in the UI. |
766
766
| Send file / nothing happens | Check the footer (**Connected** vs **Disconnected**). If disconnected, `:sendfile` should report **Not connected to server**; reconnect, then retry (including **Alt+F** after a connection is up). |
767
767
| Username already taken | A live or **stale** session may still hold the name. Admin: **`:forcedisconnect <user>`**. Otherwise the server’s **~5 minute** WebSocket ping sweep removes broken clients (or run **`:cleanup`**). |
768
768
| Stale / ghost sessions | Same as above: wait for the ping sweep, run `:cleanup`, or `:forcedisconnect`. |
Copy file name to clipboardExpand all lines: SECURITY.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -61,13 +61,13 @@ The `-doctor` / `-doctor-json` commands print masked values for sensitive `MARCH
61
61
62
62
### Client global E2E key
63
63
64
-
When the client **auto-generates** a global E2E key, it does **not** print the full base64 key to stdout (only a Key ID). Distribute the key using **`MARCHAT_GLOBAL_E2E_KEY`**, **`keystore.dat`** plus passphrase, or another channel you treat as confidential—do not rely on terminal output for key material.
64
+
When the client **auto-generates** a global E2E key, it does **not** print the full base64 key to stdout (only a Key ID). Distribute the key using **`MARCHAT_GLOBAL_E2E_KEY`**, **`keystore.dat`** plus passphrase, or another channel you treat as confidential; do not rely on terminal output for key material.
65
65
66
66
### Indirect Go modules and vulnerability scanners
67
67
68
68
Dependabot may flag **transitive** dependencies that do not expose reachable vulnerable APIs in marchat. For example, **CVE-2026-26958** ([GHSA-fw7p-63qq-7hpr](https://github.com/advisories/GHSA-fw7p-63qq-7hpr)) affects **`filippo.io/edwards25519`** before **v1.1.1** (`MultiScalarMult` receiver initialization). marchat does not use that API; the advisory notes many consumers (including typical **`github.com/go-sql-driver/mysql`** usage) are unaffected. The module is still pinned at **v1.1.1** on **`main`** to pick up the fix. For reachability, run **`govulncheck ./...`** against your build.
69
69
70
-
**Go toolchain:** Build and release with **Go 1.25.9+** (see **`go.mod`**). Go **1.25.8** and earlier are flagged by **govulncheck** for several standard-library issues fixed in **1.25.9** (for example **GO-2026-4870** / **crypto/tls**, **GO-2026-4947** / **crypto/x509**, **GO-2026-4869** / **archive/tar**). **`github.com/jackc/pgx/v5`** may still appear under **`govulncheck -show verbose`** for package-level advisories with **Fixed in: N/A**; default **`govulncheck ./...`** reports **no reachable** vulnerable call paths in this module at current versions.
70
+
**Go toolchain:** Build and release with **Go 1.25.9+** (see **`go.mod`**). Go **1.25.8** and earlier are flagged by **govulncheck** for several standard-library issues fixed in **1.25.9** (for example **GO-2026-4870** / **crypto/tls**, **GO-2026-4947** / **crypto/x509**, **GO-2026-4869** / **archive/tar**). **`github.com/jackc/pgx/v5`**(for example **GO-2026-4771** / **CVE-2026-33815** and **GO-2026-4772** / **CVE-2026-33816**) may still appear under **`govulncheck -show verbose`** for package-level advisories whose entries list **Fixed in: N/A**, even though upstream shipped related protocol hardening in **v5.9.0+**. Default **`govulncheck ./...`** reports **no reachable** vulnerable call paths in this module at current versions. Container image scanners (for example Docker Scout) often rely on similar metadata and flag **pgx** inside the compiled server binary without assessing reachability.
0 commit comments