Skip to content

Security Overview

Environment variables often store sensitive information, making secure handling critical. This document outlines the security architecture and core features of the env library.

Security Architecture

text
┌──────────────────────────────────────────────────────────────┐
│                      Application Layer                       │
├──────────────────────────────────────────────────────────────┤
│   SecureValue   │   Masking   │  Zeroing  │  Memory Locking   │
├──────────────────────────────────────────────────────────────┤
│                        Loader Layer                          │
├──────────────────────────────────────────────────────────────┤
│   Key Validation │ Value Validation │ Forbidden Keys │ Size Limits │
├──────────────────────────────────────────────────────────────┤
│                       Parsing Layer                          │
├──────────────────────────────────────────────────────────────┤
│  Format Detection │ Expansion Check │   Path Validation       │
└──────────────────────────────────────────────────────────────┘

Core Security Features

FeatureDescriptionDocumentation
SecureValueMemory protection and auto-zeroing for sensitive valuesSecureValue API
Forbidden keysPrevents modification of system-critical variablesConstants & Errors
Sensitive key detectionAuto-identifies sensitive config keys, log masking toolsData Masking
Value validationDetects control characters, null bytes, etc.Config API
Audit loggingComplete operation trackingComponent Factory

SecureValue Overview

For sensitive data, use GetSecure instead of GetString:

go
// Not recommended
password := env.GetString("DB_PASSWORD")

// Recommended
secret := env.GetSecure("DB_PASSWORD")
defer secret.Close()
password := secret.Reveal()  // Only call when plaintext is needed

Core features:

  • Memory locking - Prevents swapping to disk (Linux/macOS/Windows/FreeBSD)
  • Auto-zeroing - Safely erases memory on Close()
  • Masked display - Masked() for log output
  • Thread safety - Supports concurrent reads

Log Security

SecureValue protects sensitive values in memory, but logs, error messages, and debug output are equally prone to leaking keys. env provides a set of standalone masking utility functions that can be used without a Loader:

  • IsSensitiveKey auto-detects sensitive key names like passwords, keys, and tokens
  • MaskValue / MaskKey mask values and key names before output
  • SanitizeForLog scans log strings for key=value patterns and masks them
go
// Safely output configuration in logs, avoiding plaintext leakage
log.Printf("Loading config: %s", env.MaskValue("DB_PASSWORD", password))
// Output: Loading config: [MASKED:12 chars]

log.Printf("Connection params: %s", env.SanitizeForLog("user=admin password=s3cret"))
// Output: Connection params: user=admin [MASKED]

TIP

For complete usage of masking tools, see Data Masking.

Key/Value Validation

Key Validation

Default key name rules: ^[A-Za-z][A-Za-z0-9_]*$

  • Starts with a letter
  • Contains only letters, numbers, and underscores
  • Length does not exceed MaxKeyLength

Forbidden Keys

Built-in forbidden keys prevent modification of system-critical variables:

CategoryExamplesRisk
System pathPATH, LD_LIBRARY_PATHCommand/library hijacking
Dynamic linkingLD_PRELOAD, DYLD_INSERT_LIBRARIESMalicious library injection
ShellSHELL, IFS, BASH_ENVShell hijacking
Language runtimesPYTHONPATH, NODE_PATHModule hijacking

TIP

See DefaultForbiddenKeys for the complete forbidden keys list.

Value Validation

Enable value validation to detect potential dangers:

go
cfg := env.ProductionConfig()
cfg.ValidateValues = true  // Detect control characters, null bytes, etc.

File Security Basics

File Permissions

bash
# Readable/writable by owner only
chmod 600 .env

# Or stricter (read-only)
chmod 400 .env

Git Ignore

bash
.env
.env.local
.env.*.local
*.pem
*.key

Configuration Security Levels

PresetPurposeCharacteristics
DevelopmentConfig()DevelopmentRelaxed limits, YAML syntax support
TestingConfig()TestingOverwrites existing variables, test isolation
ProductionConfig()ProductionStrict validation + audit logging, no overwriting
go
// Recommended production configuration
cfg := env.ProductionConfig()
cfg.RequiredKeys = []string{"DB_HOST", "API_KEY"}
cfg.AllowedKeys = []string{"APP_NAME", "PORT", "DB_HOST", "API_KEY"}