Backend audit fixes (upstream-file edits wrapped in // lx: markers):
- experimental/libbox oom_report.go/report.go: OOM reports + configuration.json
(server secrets/keys) were written world-writable — 0o777 dirs / 0o666 files
→ 0o700 / 0o600. [sec-perms]
- daemon/server.go + experimental/libbox/command_server.go: gRPC auth secret
compared with != (timing oracle) → crypto/subtle.ConstantTimeCompare.
[sec-consttime]
- service/oomkiller/timer.go: network-extension cleanupTriggered logic was
inverted, so FreeOSMemory was never called after a trigger; flip both
assignments so a trigger schedules the deferred free and the next poll runs +
clears it. [sec-oomcleanup]
- transport/v2rayxhttp/client.go (lx-native file): session id used math/rand →
crypto/rand, matching Xray's uuid.New() entropy and removing the spoof surface.
- daemon/started_service_tailscale_ssh.go: forwardSSHAgentChannel leaked a
goroutine + the ssh-agent fd on every closed session (second io.Copy blocked
on an idle agent Read forever); tie both copies + the session ctx to a
cancel that closes both ends. [sec-sshagent]
- daemon/managed_service.go: TriggerOOMReport had no gate — rate-limit to
1/min so an authenticated client can't spin secret-bearing dumps. [sec-oomgate]
- route/reachability_lx.go (lx idle-suspend file): idle tick read r.idleStop in
select while stopIdleSuspend niled it after close (race + goroutine leak on
Close-during-tick); pass the stop channel to the loop by value.
go build ./... (default) and the D9 shaterd linux build (tags
with_quic,with_wireguard,with_utls,badlinkname,tfogo_checklinkname0,with_xhttp,
with_awg,with_lx_command) are green; go vet clean (2 pre-existing unsafe.Pointer
warnings in TriggerDebugCrash/debug.go, untouched); go test ./route/...
./daemon/... ./service/oomkiller/... green incl. -race with with_lx_idle_suspend
and v2rayxhttp with with_xhttp.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>