@
v0.129.0: CAMPAIGN-4 fixes — rate-limiter key (F-B) + volume-blind estimate (F-A) + no-op claim status (F-C) F-B (MED, security): shared clientIP(r) helper (XFF first-hop, else SplitHostPort host, else raw) replaces requestIP + the duplicated inline derivation in handleLogin, so login AND escrow re-auth key on the port-stripped host IP — distinct direct connections no longer evade the failed-attempt counter. XFF-trust out of scope (commented). F-A (MED, honesty): volumeSizer seam reads volume size from a container view (docker run --rm -v vol:/vol:ro alpine du -sb /vol), replacing the host-path du that returned 0 inside the containerized controller. Failed read -> size_unknown + fits_on_dest forced false (never "fits"). Export pre-flight hard-aborts only on a KNOWN doesn.t-fit. HDD branch unchanged. F-C (LOW-MED): escrowClaimAPIHandler relays agent 404 -> clean 404 and 409 -> 409; 410 and genuine-unreachable 502 unchanged (was: 404 fell through to 502). Tests + red-proofs: ratelimit_ip_test.go (F-B x6), estimate_volsize_test.go (F-A x3), TestEscrowClaim_ProxySemantics +3 (F-C). Alpine busybox du -sb verified prod-valid. Claude-Session: https://claude.ai/code/session_01LbMm4T7Ayzs1unB9pN6Uqd @
This commit is contained in:
@@ -1,5 +1,41 @@
|
||||
## Changelog
|
||||
|
||||
### v0.129.0 — CAMPAIGN-4 fixes: rate-limiter key (F-B) + volume-blind estimate (F-A) + no-op claim status (F-C) (2026-07-14)
|
||||
|
||||
Three controller-side fixes from CAMPAIGN-4 (2026-07-13). Controller-only.
|
||||
|
||||
- **F-B (MED, security):** the login/escrow-reauth rate-limiter keyed on `r.RemoteAddr` (which is
|
||||
`IP:PORT`) whenever `X-Forwarded-For` was absent, so every fresh direct connection from one host
|
||||
got a distinct ephemeral port → a distinct key → the failed-attempt counter never accrued. A
|
||||
direct-to-controller path (LAN/guest, bypassing the traefik/CF proxy) therefore had **no
|
||||
brute-force protection**. Fix: a single shared `clientIP(r)` helper (XFF first-hop, else
|
||||
`net.SplitHostPort(RemoteAddr)` host, else raw) — replaces the former `requestIP` and the
|
||||
duplicated inline derivation in `handleLogin`, so the escrow re-auth limiter shares the exact same
|
||||
fixed key. Accepted limitation (out of scope, commented): XFF is attacker-controlled on a direct
|
||||
path — the fix closes the port-in-key bug, not XFF trust. Red-proof: revert `clientIP` to raw
|
||||
`RemoteAddr` → the distinct-ports scenario stops limiting and escrow re-auth stays 401 not 429.
|
||||
- **F-A (MED, honesty):** the export size-estimate's volume branch `du`'d the raw host mountpoint
|
||||
from `docker volume inspect`, which is not mounted inside the containerized controller → returned
|
||||
0, so a >1 GB volume-only app reported `data_size_bytes:0` / "3.6 KB" / `fits_on_dest:true`. Fix:
|
||||
a `volumeSizer` seam whose real impl reads the size from a **container view** (`docker run --rm -v
|
||||
<vol>:/vol:ro alpine du -sb /vol` — the same named-volume pattern the export path uses; never a
|
||||
controller-host path, the v0.125.0 strand class). A failed read now sets `size_unknown` and
|
||||
**forces `fits_on_dest:false`** (never renders as "fits") with the human string "ismeretlen méret".
|
||||
The export pre-flight hard-aborts only on a KNOWN doesn't-fit (an unmeasured size no longer blocks
|
||||
the export — the tar stream + destination FS surface a real ENOSPC). HDD-path branch unchanged.
|
||||
Red-proof: revert the estimate to the host-path read → the >1 GiB scenario reads 0.
|
||||
- **F-C (LOW-MED, correctness):** a no-op escrow claim (agent `phase:none` → HTTP 404) fell through
|
||||
`escrowClaimAPIHandler` to a generic **502**. Fix: relay the agent's 404 as a clean 404 ("Nincs
|
||||
aktív helyreállítási folyamat…") and 409 as 409; 410 (void) and a genuinely-unreachable agent
|
||||
(status 0 → real bad gateway) are unchanged. Red-proof: remove the 404 mapping → the no-ceremony
|
||||
claim returns 502.
|
||||
|
||||
Tests (non-hollow, all red-proofed): `ratelimit_ip_test.go` (F-B: 6 — direct-distinct-ports,
|
||||
stable-XFF, rotating-XFF, escrow-reauth-shared-key, success-clears, clientIP unit),
|
||||
`estimate_volsize_test.go` (F-A: 3 — real-not-zero, failure-never-fits, HDD-unchanged),
|
||||
`TestEscrowClaim_ProxySemantics` +3 subtests (F-C: 404-not-502, 409, unreachable-stays-502). Live:
|
||||
Alpine busybox `du -sb` verified supported (prod-valid).
|
||||
|
||||
### v0.128.1 — USB drives never show the rotational class hint (2026-07-13, ruling F5)
|
||||
|
||||
`storage.html` `classTag(d)`: `if(d.type==='usb') return '';` ahead of the class branches —
|
||||
|
||||
Reference in New Issue
Block a user