Fix ECDH zeroization, add audit logging, and remediate high findings

- Fix #61: handleRotateKey and handleDeleteUser now zeroize stored
  privBytes instead of calling Bytes() (which returns a copy). New
  state populates privBytes; old references nil'd for GC.
- Add audit logging subsystem (internal/audit) with structured event
  recording for cryptographic operations.
- Add audit log engine spec (engines/auditlog.md).
- Add ValidateName checks across all engines for path traversal (#48).
- Update AUDIT.md: all High findings resolved (0 open).
- Add REMEDIATION.md with detailed remediation tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 14:04:39 -07:00
parent b33d1f99a0
commit 5c5d7e184e
24 changed files with 1699 additions and 72 deletions

View File

@@ -23,7 +23,7 @@ func setupSeal(t *testing.T) (*Manager, func()) {
t.Fatalf("migrate: %v", err)
}
b := barrier.NewAESGCMBarrier(database)
mgr := NewManager(database, b, slog.Default())
mgr := NewManager(database, b, nil, slog.Default())
return mgr, func() { _ = database.Close() }
}
@@ -103,7 +103,7 @@ func TestSealCheckInitializedPersists(t *testing.T) {
database, _ := db.Open(dbPath)
_ = db.Migrate(database)
b := barrier.NewAESGCMBarrier(database)
mgr := NewManager(database, b, slog.Default())
mgr := NewManager(database, b, nil, slog.Default())
_ = mgr.CheckInitialized()
params := crypto.Argon2Params{Time: 1, Memory: 64 * 1024, Threads: 1}
_ = mgr.Initialize(context.Background(), []byte("password"), params)
@@ -113,7 +113,7 @@ func TestSealCheckInitializedPersists(t *testing.T) {
database2, _ := db.Open(dbPath)
defer func() { _ = database2.Close() }()
b2 := barrier.NewAESGCMBarrier(database2)
mgr2 := NewManager(database2, b2, slog.Default())
mgr2 := NewManager(database2, b2, nil, slog.Default())
_ = mgr2.CheckInitialized()
if mgr2.State() != StateSealed {
t.Fatalf("state after reopen: got %v, want Sealed", mgr2.State())