From dbe5360ad3c28903617f27951b9f6a1bf770bd92 Mon Sep 17 00:00:00 2001 From: matthew-pilot Date: Sat, 30 May 2026 13:56:03 +0000 Subject: [PATCH] fix: zero old private key after RotateKey (PILOT-294) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After RotateKey succeeds, the old identity's ed25519.PrivateKey remained on the heap until GC — which in a long-lived daemon can be hours. Explicitly zero the old key bytes before discard to prevent core-dump / ptrace / swap-file leaks. 1 file, +6 lines. --- pkg/daemon/daemon.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go index 099eba10..2ece8db9 100644 --- a/pkg/daemon/daemon.go +++ b/pkg/daemon/daemon.go @@ -2054,6 +2054,13 @@ func (d *Daemon) RotateKey() (map[string]interface{}, error) { d.identity = newID d.identityMu.Unlock() + // Zero the old private key so it doesn't linger on the heap + // until GC — a long-lived daemon can keep it alive for hours. + // ed25519.PrivateKey is a []byte (seed || public). + for i := range current.PrivateKey { + current.PrivateKey[i] = 0 + } + d.tunnels.SetIdentity(newID) // The signer installed in Start() reads d.identity under d.identityMu // on every call, so this SetSigner re-bind is no longer load-bearing —