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

@@ -588,6 +588,9 @@ func (e *SSHCAEngine) handleUpdateProfile(ctx context.Context, req *engine.Reque
if name == "" {
return nil, fmt.Errorf("sshca: name is required")
}
if err := engine.ValidateName(name); err != nil {
return nil, err
}
// Load existing profile.
profile, err := e.loadProfile(ctx, name)
@@ -631,6 +634,9 @@ func (e *SSHCAEngine) handleGetProfile(ctx context.Context, req *engine.Request)
if name == "" {
return nil, fmt.Errorf("sshca: name is required")
}
if err := engine.ValidateName(name); err != nil {
return nil, err
}
profile, err := e.loadProfile(ctx, name)
if err != nil {
@@ -697,6 +703,9 @@ func (e *SSHCAEngine) handleDeleteProfile(ctx context.Context, req *engine.Reque
if name == "" {
return nil, fmt.Errorf("sshca: name is required")
}
if err := engine.ValidateName(name); err != nil {
return nil, err
}
// Check existence.
if _, err := e.barrier.Get(ctx, e.mountPath+"profiles/"+name+".json"); err != nil {