Files
gnoma/internal/security/incognito.go
vikingowl 33dec722b8 feat: add security firewall with secret scanning and incognito mode
internal/security/ — core security layer baked into gnoma:
- Secret scanner: gitleaks-derived regex patterns (Anthropic, OpenAI,
  AWS, GitHub, GitLab, Slack, Stripe, private keys, DB URLs, generic
  secrets) + Shannon entropy detection for unknown formats
- Redactor: replaces matched secrets with [REDACTED], merges
  overlapping ranges, preserves surrounding context
- Unicode sanitizer: NFKC normalization, strips Cf/Co categories,
  tag characters (ASCII smuggling), zero-width chars, RTL overrides
- Incognito mode: suppresses persistence, learning, content logging
- Firewall: wraps engine, scans outgoing messages + system prompt +
  tool results before they reach the provider

Wired into engine and CLI. 21 security tests.
2026-04-03 14:07:50 +02:00

58 lines
1.1 KiB
Go

package security
import "sync"
// IncognitoMode controls privacy-sensitive behavior.
// When active: no persistence, no learning, no content logging.
type IncognitoMode struct {
mu sync.RWMutex
active bool
// Options
LocalOnly bool // only route to local arms when incognito
}
func NewIncognitoMode() *IncognitoMode {
return &IncognitoMode{}
}
func (m *IncognitoMode) Activate() {
m.mu.Lock()
defer m.mu.Unlock()
m.active = true
}
func (m *IncognitoMode) Deactivate() {
m.mu.Lock()
defer m.mu.Unlock()
m.active = false
}
func (m *IncognitoMode) Toggle() bool {
m.mu.Lock()
defer m.mu.Unlock()
m.active = !m.active
return m.active
}
func (m *IncognitoMode) Active() bool {
m.mu.RLock()
defer m.mu.RUnlock()
return m.active
}
// ShouldPersist returns false when incognito is active.
func (m *IncognitoMode) ShouldPersist() bool {
return !m.Active()
}
// ShouldLearn returns false when incognito is active (no router feedback).
func (m *IncognitoMode) ShouldLearn() bool {
return !m.Active()
}
// ShouldLogContent returns false when incognito is active.
func (m *IncognitoMode) ShouldLogContent() bool {
return !m.Active()
}