Skip to content

sudoki2015/sensitive

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sensitive πŸ›‘οΈ

Go Reference
Go Report Card
License: MIT

A thread-safe, zero-dependency Go package for detecting and masking sensitive data in logs, API responses, and configuration dumps.

✨ Features

  • πŸ”’ Multiple masking strategies: Full redaction, partial masking, SHA256 hashing, or passthrough
  • 🌳 Recursive processing: Automatically handles nested map[string]any, []any, and slices
  • πŸ“¦ JSON integration: Drop-in json.Marshal replacement & SensitiveValue wrapper for automatic masking
  • πŸŽ›οΈ Environment presets: Strict (prod), Audit (logging), Debug (development)
  • βœ… Validated configuration: Atomic updates with runtime validation
  • 🧡 Thread-safe: sync.RWMutex protection for all config mutations
  • 🚫 Zero dependencies: Pure standard library
  • πŸ”„ Backward compatible: Simple IsSensitive / Redact API still works

πŸ“¦ Installation

go get github.com/sudoki2015/sensitive

πŸš€ Quick Start

package main

import (
	"fmt"
	"github.com/sudoki2015/sensitive"
)

func main() {
	// 1. Apply a preset for your environment
	_ = sensitive.ApplyPreset(sensitive.PresetStrict)

	// 2. Mask individual values
	fmt.Println(sensitive.MaskValue("password", "SuperSecret123")) 
	// β†’ [REDACTED]
	
	fmt.Println(sensitive.MaskValue("email", "alice@example.com")) 
	// β†’ al********@example.com

	// 3. Mask complex structures recursively
	data := map[string]any{
		"user":     "alice",
		"password": "secret",
		"meta":     map[string]any{"token": "jwt_xyz"},
	}
	masked := sensitive.RedactAny(data)
	// β†’ map[user:alice password:[REDACTED] meta:map[token:[REDACTED]]]
}

πŸŽ›οΈ Configuration & Presets

Built-in Presets

Preset Strategy Use Case
PresetStrict Full redaction for secrets, partial for PII Production logs, external APIs
PresetAudit Hash tokens, mask secrets, partial PII Debugging, compliance audits
PresetDebug Hash secrets, expose non-critical fields Local development, staging
// Apply preset (validates automatically)
if err := sensitive.ApplyPreset(sensitive.PresetAudit); err != nil {
	log.Fatalf("invalid preset: %v", err)
}

Custom Field Configuration

_ = sensitive.SetFieldConfig("customer_phone", sensitive.FieldConfig{
	Strategy: sensitive.StrategyPartialMask,
	Options: sensitive.MaskOptions{
		VisiblePrefix: 3,
		VisibleSuffix: 2,
		MaskChar:      'β€’',
		MinLength:     10,
	},
})

fmt.Println(sensitive.MaskValue("customer_phone", "+79991234567"))
// β†’ +79β€’β€’β€’β€’β€’β€’β€’67

Global Config & Validation

cfg := sensitive.Config{
	DefaultStrategy: sensitive.StrategyPartialMask,
	MaxDepth:        10,
	Enabled:         true,
}

if err := cfg.Validate(); err != nil {
	// Handle invalid config (e.g., negative VisiblePrefix)
}

_ = sensitive.UpdateConfig(cfg) // Atomic, validated update

πŸ” Advanced Usage

πŸ” Recursive Masking

RedactAny walks any Go type, masking sensitive keys at any depth. Depth is limited by Config.MaxDepth to prevent abuse.

payload := []any{
	map[string]any{"email": "user@test.com"},
	map[string]any{"api_key": "sk_live_xxx"},
}
safe := sensitive.RedactAny(payload)

πŸ“¦ JSON Serialization

Option 1: sensitive.Marshal

Drop-in replacement for json.Marshal that applies masking before encoding.

logEntry := map[string]any{"email": "a@b.com", "token": "abc"}
jsonBytes, _ := sensitive.Marshal(logEntry) // token & email masked

Option 2: SensitiveValue Struct Tag

Wrap sensitive fields in your structs for automatic masking during marshaling.

type LoginRequest struct {
	Username string                   `json:"username"`
	Password sensitive.SensitiveValue `json:"password"`
}

req := LoginRequest{
	Username: "alice",
	Password: sensitive.NewSensitive("password", "MyP@ss!"),
}

json.Marshal(req) // β†’ {"username":"alice","password":"[REDACTED]"}

🌐 URL & Query Strings

// Raw query
sensitive.RedactRawQuery("user=alice&password=123&redirect=/home")
// β†’ user=alice&password=[REDACTED]&redirect=/home

// url.Values
values := url.Values{"email": {"a@b.com"}, "csrf_token": {"tok"}}
safe := sensitive.RedactValues(values)

⚠️ Security Notice

  • πŸ” This package does not encrypt data. It only masks values for output/logging.
  • 🚫 Never use PresetDebug in production or public-facing environments.
  • πŸ“ Apply masking at the boundary (before writing to logs, sending HTTP responses, or storing in tracing systems), not inside business logic.
  • πŸ” SensitiveValue.UnmarshalJSON returns the original value. Use it only for outgoing data.
  • πŸ›‘οΈ For data at rest or in transit, always use proper cryptographic libraries (e.g., crypto/aes, crypto/tls).

πŸ§ͺ Testing & Benchmarks

# Run all tests + examples
go test ./... -v

# Run only example tests (validates output)
go test ./... -run=Example -v

# Benchmarks (performance profiling)
go test ./... -bench=. -benchmem -benchtime=5s

# Coverage report
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.out

πŸ“– API Reference

Function Description
IsSensitive(name string) bool Check if a field name is marked as sensitive
MaskValue(key, value string) string Apply configured strategy to a value
RedactAny(v any) any Recursively mask maps, slices, and nested structures
Marshal(v any) ([]byte, error) JSON marshal with automatic masking
ApplyPreset(PresetType) error Atomically apply & validate a preset configuration
SetFieldConfig(string, FieldConfig) error Override strategy/options for a specific field
NewSensitive(field, value string) SensitiveValue Create JSON-marshalable sensitive wrapper
RedactRawQuery(string) string Mask sensitive parameters in URL query strings
Enable(bool) / Reset() Toggle globally or reset to defaults (useful in tests)

Full documentation: pkg.go.dev/github.com/sudoki2015/sensitive

🀝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing)
  3. Run tests & benchmarks (go test ./... -v)
  4. Commit your changes (git commit -m 'feat: add amazing feature')
  5. Push to the branch (git push origin feature/amazing)
  6. Open a Pull Request

πŸ“œ License

MIT License. See LICENSE for details.


Built for developers who care about data privacy without sacrificing DX. πŸ”

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages