|
1 | 1 | # Changelog |
2 | 2 |
|
| 3 | +## v0.13.0 (2026-06-19) |
| 4 | + |
| 5 | +A hardening release: no new user-facing features, but three real bugs |
| 6 | +found by expanding the static-analysis linter set, plus a sweep of |
| 7 | +Go 1.22–1.26 modernisation and tighter file permissions across the |
| 8 | +entire `~/.cmdguard` tree. |
| 9 | + |
| 10 | +### Bug fixes (found by new linters) |
| 11 | + |
| 12 | +- **Dead `reasonTimeout` enum value.** The `nonTTYReason` type declared |
| 13 | + `reasonTimeout` but the `emitNonTTYRejection` switch never handled |
| 14 | + it — timeout rejection goes through a separate function. Removed |
| 15 | + the dead value; `exhaustive` now verifies every `switch` on the |
| 16 | + type covers all declared cases. |
| 17 | +- **Duplicate "agent" in bypass help text.** The 4-segment identifier |
| 18 | + table printed `agent agent id`, which `dupword` flagged. Changed |
| 19 | + to `agent unique identifier`. |
| 20 | +- **Possible nil dereference after `os.Exit`.** `staticcheck SA5011` |
| 21 | + reported that after the `if entry == nil { os.Exit(1) }` guard, |
| 22 | + `entry.Expired` dereferences a pointer that the analyser cannot prove |
| 23 | + is non-nil (because it doesn't know `os.Exit` never returns). Added |
| 24 | + an unreachable `return` to close the path. |
| 25 | + |
| 26 | +### File permissions tightened |
| 27 | + |
| 28 | +Every file and directory under `~/.cmdguard` is now owner-only: |
| 29 | + |
| 30 | +| Path | Before | After | |
| 31 | +|------------------------------|--------|-------| |
| 32 | +| vault root dir | 0755 | 0700 | |
| 33 | +| vault per-backup dir | 0755 | 0700 | |
| 34 | +| vault files/ subdirs | 0755 | 0700 | |
| 35 | +| manifest.json | 0644 | 0600 | |
| 36 | +| backup/ dir (init --force) | 0755 | 0700 | |
| 37 | +| config dir / bin / log / vault| 0755 | 0700 | |
| 38 | +| config.toml | 0644 | 0600 | |
| 39 | +| wrapper scripts (rm/mv/chmod)| 0755 | 0700 | |
| 40 | +| audit log | 0644 | 0600 | |
| 41 | + |
| 42 | +Rationale: the vault holds copies of files the user just deleted |
| 43 | +(`~/.ssh/id_rsa`, `/etc/shadow`, …). A world-readable manifest |
| 44 | +advertising the existence of those originals defeats the purpose |
| 45 | +of deleting them. |
| 46 | + |
| 47 | +### Go 1.22–1.26 modernisation |
| 48 | + |
| 49 | +- `strings.HasPrefix` + `TrimPrefix` → `strings.CutPrefix` |
| 50 | +- `strings.HasSuffix` + `TrimSuffix` → `strings.CutSuffix` |
| 51 | +- `strings.Split` → `strings.SplitSeq` (lazy iteration) |
| 52 | +- manual loop → `slices.Contains` |
| 53 | +- `if/else` clamp → `min()` builtin |
| 54 | +- `interface{}` → `any` |
| 55 | +- `wg.Add(1); go func(){ defer wg.Done(); … }()` → `wg.Go(func(){ … })` |
| 56 | +- `for i := 0; i < N; i++` → `for i := range N` |
| 57 | +- `fmt.Errorf("literal")` → `errors.New` |
| 58 | +- `fmt.Sprintf("%d", n)` → `strconv.Itoa(n)` |
| 59 | +- `string +=` in loop → `strings.Builder` |
| 60 | + |
| 61 | +### Static-analysis configuration |
| 62 | + |
| 63 | +`.golangci.yml` expanded from 5 linters to **37** (of 113 available). |
| 64 | +The new additions caught the three bugs listed above, plus a batch of |
| 65 | +modernisation and performance issues. `govulncheck` reports no known |
| 66 | +vulnerabilities. |
| 67 | + |
| 68 | +gosec false positives (cmdguard intentionally launches user-supplied |
| 69 | +commands and reads variable paths) are suppressed per-site with |
| 70 | +`// #nosec` directives, each with a justification comment. |
| 71 | + |
3 | 72 | ## v0.12.0 (2026-06-19) |
4 | 73 |
|
5 | 74 | Big jump from v0.6.0 to mark the work density: four new features |
|
0 commit comments