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

@@ -16,6 +16,17 @@ type Config struct {
Database DatabaseConfig `toml:"database"`
Log LogConfig `toml:"log"`
Seal SealConfig `toml:"seal"`
Audit AuditConfig `toml:"audit"`
}
// AuditConfig holds audit logging settings.
type AuditConfig struct {
// Mode controls audit log output: "file", "stdout", or "" (disabled).
Mode string `toml:"mode"`
// Path is the audit log file path (required when mode is "file").
Path string `toml:"path"`
// IncludeReads enables audit logging for read-only operations.
IncludeReads bool `toml:"include_reads"`
}
// ServerConfig holds HTTP/gRPC server settings.
@@ -119,5 +130,17 @@ func (c *Config) Validate() error {
c.Web.ListenAddr = "127.0.0.1:8080"
}
// Validate audit config.
switch c.Audit.Mode {
case "", "stdout":
// ok
case "file":
if c.Audit.Path == "" {
return fmt.Errorf("config: audit.path is required when audit.mode is \"file\"")
}
default:
return fmt.Errorf("config: audit.mode must be \"file\", \"stdout\", or empty")
}
return nil
}