You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

encrypted-env-loader

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

encrypted-env-loader

Securely load and manage encrypted environment variables

0.3.0
pipPyPI
Maintainers
1

Encrypted Environment Loader

A secure Python package for managing encrypted environment variables. Load sensitive configuration from encrypted .env files using Fernet encryption, with convenient keyring integration for local development.

Features

  • Secure encryption using Fernet (AES 128 in CBC mode with HMAC-SHA256)
  • Keyring integration for secure local key storage (macOS Keychain, Windows Credential Manager, Linux Secret Service)
  • Profile support for multiple environments (dev, prod, test, etc.)
  • CLI tools for file management and subprocess execution
  • Python API with context managers and decorators
  • Shell integration for fish, bash, and zsh
  • Safe editing with backup and validation
  • CI/CD friendly with quiet modes and secret masking
  • Modern Python with type hints and proper packaging

Installation

pip install encrypted-env-loader

Quick Start

1. Initialize a new encrypted environment file

# Generate new encrypted file with random key
encrypted-env init
# Output: Encryption key: gAAAAABh...
# Output: Set your encryption key: export ENCRYPTED_ENV_KEY='gAAAAABh...'

# Set the key in your shell
export ENCRYPTED_ENV_KEY='gAAAAABh...'

2. Edit your environment variables

# Opens decrypted content in $EDITOR, re-encrypts on save
encrypted-env edit

3. Run commands with encrypted environment

# Run any command with encrypted env loaded
encrypted-env run -- python app.py
encrypted-env run -- ./deploy.sh

Or use shell integration

# Load into current shell (fish)
eval (encrypted-env load)

# Load into current shell (bash/zsh)  
eval $(encrypted-env load)

Keyring Integration (New in v0.2.0)

For local development, store encryption keys securely in your system keyring instead of environment variables:

1. Store key in keyring

# Generate and store key for default profile
encrypted-env keyring set-key

# Store key for specific environment
encrypted-env keyring set-key --profile dev
encrypted-env keyring set-key --profile prod

2. Use encrypted environment with keyring

# Automatically uses keyring-stored key
encrypted-env run --profile dev -- python app.py
encrypted-env load --profile dev
encrypted-env edit --profile dev

3. Production/CI usage

# Force environment variable usage (skip keyring)
encrypted-env run --profile prod --no-keyring -- ./deploy.sh
export ENCRYPTED_ENV_KEY="your-key-here"
encrypted-env load --profile prod --no-keyring

4. Manage keyring keys

# List stored keys
encrypted-env keyring list-keys

# Retrieve a key  
encrypted-env keyring get-key --profile dev

# Delete a key
encrypted-env keyring delete-key --profile dev

Key Benefits:

  • 🔐 Secure: Keys stored in OS-native keyring (never in plaintext)
  • 🚀 Convenient: No need to manage environment variables locally
  • 🔄 Flexible: Fallback to environment variables for production/CI
  • 📋 Profile-aware: Separate keys per environment automatically

Security Features

CI/CD Safe Operations

All commands support --quiet mode for CI environments and have secure defaults:

# Generate keys silently (CI-safe)
KEY=$(encrypted-env generate-key --quiet)

# Show variable names only (never exposes values)
encrypted-env show --names-only

# Validate files without output (exit codes only)
encrypted-env validate --quiet

Secret Masking

By default, commands mask sensitive values:

# Safe - shows masked values
encrypted-env show
# Output: DATABASE_URL=***
#         API_KEY=***

# Requires explicit flag to show values
encrypted-env show --show-values  # WARNING: exposes secrets

Examples and Testing

Run the comprehensive demo to see all features:

# Interactive demo with full output
./examples/demo.sh

# CI-friendly mode (no secrets exposed)
./examples/demo.sh --ci

# View usage examples
./examples/basic_usage.sh

CLI Reference

Core Operations

run - Execute commands with encrypted environment

encrypted-env run [--file FILE] [--profile PROFILE] [--no-keyring] -- <command>

# Examples
encrypted-env run -- python app.py
encrypted-env run --profile prod -- ./deploy.sh
encrypted-env run --file .env.custom.encrypted -- npm start
encrypted-env run --profile dev --no-keyring -- python app.py  # force env var usage

load - Generate shell commands to load environment

encrypted-env load [--file FILE] [--profile PROFILE] [--shell SHELL] [--quiet] [--no-keyring]

# Usage in fish shell
eval (encrypted-env load)
eval (encrypted-env load --profile dev)
eval (encrypted-env load --profile prod --no-keyring)  # force env var usage

# Usage in bash/zsh
eval $(encrypted-env load)
eval $(encrypted-env load --profile prod)

clear - Generate shell commands to clear environment

encrypted-env clear [--file FILE] [--profile PROFILE] [--shell SHELL] [--quiet] [--no-keyring]

# Usage
eval (encrypted-env clear)  # fish
eval $(encrypted-env clear)  # bash/zsh

File Management

init - Create new encrypted environment file

encrypted-env init [--file FILE] [--profile PROFILE] [--key-file KEYFILE] [--quiet]

# Examples
encrypted-env init                           # creates .env.encrypted
encrypted-env init --profile dev             # creates .env.dev.encrypted  
encrypted-env init --key-file .env.key      # saves key to file
encrypted-env init --quiet                   # CI-friendly (key only)

encrypt - Encrypt existing .env file

encrypted-env encrypt <source> [--output OUTPUT] [--profile PROFILE] [--quiet]

# Examples
encrypted-env encrypt .env                   # creates .env.encrypted
encrypted-env encrypt .env.dev --profile dev  # creates .env.dev.encrypted
encrypted-env encrypt .env --output custom.encrypted

decrypt - Decrypt to filesystem

encrypted-env decrypt [--file FILE] [--output OUTPUT] [--profile PROFILE] [--quiet]

# Examples
encrypted-env decrypt                        # decrypts to .env
encrypted-env decrypt --profile dev         # decrypts .env.dev.encrypted to .env
encrypted-env decrypt --output .env.backup  # custom output file

edit - Safely edit encrypted files

encrypted-env edit [--file FILE] [--profile PROFILE] [--quiet]

# Opens in $EDITOR (vi by default)
# Creates backup before editing
# Validates .env format before re-encrypting
encrypted-env edit --profile prod

Key Management

generate-key - Generate new encryption key

encrypted-env generate-key [--quiet]

# Interactive mode
encrypted-env generate-key
# Output: Generated key: gAAAAABh...

# CI mode
encrypted-env generate-key --quiet
# Output: gAAAAABh...

rekey - Change encryption key

encrypted-env rekey [--file FILE] [--profile PROFILE] [--old-key-env VAR] [--new-key-env VAR] [--quiet]

# Examples
ENCRYPTED_ENV_KEY="old_key" NEW_KEY="new_key" encrypted-env rekey --new-key-env NEW_KEY
encrypted-env rekey --quiet  # generates new random key silently

Keyring Management (New in v0.2.0)

keyring set-key - Store encryption key in system keyring

encrypted-env keyring set-key [--profile PROFILE] [--key KEY] [--quiet]

# Examples
encrypted-env keyring set-key                    # generates key for default profile
encrypted-env keyring set-key --profile dev     # generates key for dev profile
encrypted-env keyring set-key --key "ABC123"    # store specific key
encrypted-env keyring set-key --quiet           # CI-friendly output

keyring get-key - Retrieve encryption key from keyring

encrypted-env keyring get-key [--profile PROFILE] [--quiet]

# Examples
encrypted-env keyring get-key                    # get default profile key
encrypted-env keyring get-key --profile dev     # get dev profile key  
encrypted-env keyring get-key --quiet           # key only, no messages

keyring delete-key - Remove encryption key from keyring

encrypted-env keyring delete-key [--profile PROFILE] [--quiet]

# Examples  
encrypted-env keyring delete-key                 # delete default profile key
encrypted-env keyring delete-key --profile dev  # delete dev profile key
encrypted-env keyring delete-key --quiet        # no confirmation prompt

keyring list-keys - List all profiles with stored keys

encrypted-env keyring list-keys [--quiet]

# Example output:
# Found keys for 3 profiles:
#   - default
#   - dev  
#   - prod

# Quiet mode (CI-friendly)
encrypted-env keyring list-keys --quiet
# Output: default
#         dev
#         prod

Keyring Key Storage:

  • Service name: Git repository name (e.g., encrypted-env-loader)
  • Username format: {profile}-key (e.g., dev-key, default-key)
  • Automatic detection: Git repo name used for consistent keyring service naming

Utilities

status - Show file information and variables

encrypted-env status [--file FILE] [--profile PROFILE] [--no-keyring]

# Example output with keyring:
# File: .env.encrypted
# Exists: True
# Size: 1024 bytes
# Key source: keyring (profile: default)
# Status: Valid (contains 5 variables)
# Variables:
#   - DATABASE_URL
#   - SECRET_KEY

# Example output with environment variable:
# File: .env.encrypted  
# Exists: True
# Size: 1024 bytes
# Key source: $ENCRYPTED_ENV_KEY
# Status: Valid (contains 5 variables)
# Variables:
#   - DATABASE_URL
#   - SECRET_KEY

# With --no-keyring flag:
# Key source: $ENCRYPTED_ENV_KEY (not found)
# Status: Cannot validate (no key)

validate - Check if file can be decrypted

encrypted-env validate [--file FILE] [--profile PROFILE] [--quiet] [--no-keyring]
# Exit code 0 if valid, 1 if invalid

show - Display variables (with security options)

encrypted-env show [--file FILE] [--profile PROFILE] [--names-only] [--show-values] [--no-keyring]

# Safe default (masks values)
encrypted-env show
# Output: DATABASE_URL=***

# CI-safe (names only)
encrypted-env show --names-only
# Output: DATABASE_URL
#         API_KEY

# Explicit flag required to show values
encrypted-env show --show-values  # WARNING: exposes secrets

Python API

Basic Usage

from encrypted_env_loader import load_encrypted_env

# Load with default settings (.env.encrypted, keyring or ENCRYPTED_ENV_KEY)
env_vars = load_encrypted_env()

# Load with specific parameters
env_vars = load_encrypted_env(
    key="base64-encoded-key",
    file_path=".env.prod.encrypted",
    profile="prod",
    change_os_env=True,  # Updates os.environ
    use_keyring=True     # Try keyring first (default: True)
)

# Force environment variable usage (skip keyring)
env_vars = load_encrypted_env(
    profile="prod",
    use_keyring=False
)

Context Manager

from encrypted_env_loader import encrypted_env_context
import os

with encrypted_env_context(profile="dev"):
    # Environment variables loaded here (uses keyring automatically)
    database_url = os.getenv("DATABASE_URL")
    secret_key = os.getenv("SECRET_KEY")
# Environment automatically restored when exiting context

# Force environment variable usage  
with encrypted_env_context(profile="prod", use_keyring=False):
    # Uses ENCRYPTED_ENV_KEY environment variable
    pass

Decorator

from encrypted_env_loader import with_encrypted_env
import os

@with_encrypted_env(profile="prod")
def deploy_application():
    # Function runs with encrypted env loaded (keyring first, then env var)
    api_key = os.getenv("API_KEY")
    database_url = os.getenv("DATABASE_URL")
    # Environment restored after function returns

@with_encrypted_env(profile="prod", use_keyring=False)
def ci_deploy():
    # Force environment variable usage for CI/production
    pass

deploy_application()

Keyring Functions (New in v0.2.0)

from encrypted_env_loader import (
    get_key_from_keyring,
    set_key_in_keyring,
    delete_key_from_keyring,
    list_keyring_profiles,
    get_git_repo_name
)

# Get git repository name (used for keyring service name)
repo_name = get_git_repo_name()  # e.g., "my-project"

# Store key in keyring
success = set_key_in_keyring("my-secret-key", profile="dev")

# Retrieve key from keyring  
key = get_key_from_keyring(profile="dev")

# List profiles with stored keys
profiles = list_keyring_profiles()  # ["default", "dev", "prod"]

# Delete key from keyring
success = delete_key_from_keyring(profile="dev")

Utility Functions

from encrypted_env_loader import (
    generate_key,
    encrypt_env_file,
    decrypt_env_file,
    validate_encrypted_file
)

# Generate encryption key
key = generate_key()

# Encrypt a file (supports keyring)
encrypt_env_file(".env", ".env.encrypted", key)
encrypt_env_file(".env", ".env.encrypted", profile="dev")  # uses keyring
encrypt_env_file(".env", ".env.encrypted", profile="dev", use_keyring=False)  # force env var

# Decrypt and get variables (supports keyring)
env_vars = decrypt_env_file(".env.encrypted", key=key)
env_vars = decrypt_env_file(".env.encrypted", profile="dev")  # uses keyring
env_vars = decrypt_env_file(".env.encrypted", profile="dev", use_keyring=False)  # force env var

# Validate file (supports keyring)
is_valid = validate_encrypted_file(".env.encrypted", key=key)
is_valid = validate_encrypted_file(".env.encrypted", profile="dev")  # uses keyring
is_valid = validate_encrypted_file(".env.encrypted", profile="dev", use_keyring=False)  # force env var

Profiles

Profiles allow managing multiple environment configurations:

# Profile-based file naming
.env.encrypted          # default profile
.env.dev.encrypted      # dev profile  
.env.prod.encrypted     # prod profile
.env.test.encrypted     # test profile

# Usage
encrypted-env init --profile dev
encrypted-env run --profile prod -- python app.py
encrypted-env edit --profile test

Shell Integration

Fish Shell

# Load environment
eval (encrypted-env load --profile dev)

# Clear environment  
eval (encrypted-env clear --profile dev)

# One-liner with auto-clear
encrypted-env run --profile dev -- python app.py

Bash/Zsh

# Load environment
eval $(encrypted-env load --profile dev)

# Clear environment
eval $(encrypted-env clear --profile dev)

# Use in loops (eval once, use many times)
eval $(encrypted-env load)
for i in {1..100}; do
    curl -H "Authorization: $SECRET_TOKEN" api.example.com/data/$i
done
eval $(encrypted-env clear)

CI/CD Integration

GitHub Actions Example

- name: Setup encrypted environment
  run: |
    # Generate or retrieve key securely
    echo "${{ secrets.ENCRYPTED_ENV_KEY }}" > .env.key
    export ENCRYPTED_ENV_KEY=$(cat .env.key)
    
    # Validate encrypted file
    encrypted-env validate --quiet
    
    # Run tests with encrypted environment
    encrypted-env run -- pytest

Security Best Practices

# Never expose secrets in CI logs
encrypted-env show --names-only          # ✅ Safe
encrypted-env validate --quiet           # ✅ Safe  
encrypted-env generate-key --quiet       # ✅ Safe

# Avoid these in CI
encrypted-env show --show-values         # ❌ Exposes secrets
encrypted-env status                     # ❌ May expose info

Security Considerations

  • Key Storage: Never commit encryption keys to version control
  • Key Rotation: Regularly rotate encryption keys using rekey command
  • File Permissions: Ensure encrypted files have appropriate permissions
  • Backup Strategy: Keep secure backups of both encrypted files and keys
  • Environment Isolation: Use profiles to separate dev/staging/prod secrets
  • CI/CD Safety: Use --quiet and --names-only flags in automated environments

Error Handling

The package provides specific exception types:

from encrypted_env_loader import EncryptedEnvError, DecryptionError, KeyError

try:
    load_encrypted_env()
except KeyError:
    print("Encryption key missing or invalid")
except DecryptionError:
    print("File cannot be decrypted - wrong key or corrupted data")
except EncryptedEnvError:
    print("General error with encrypted environment operations")

Development

Setup

git clone https://github.com/igutekunst/encrypted-env-loader
cd encrypted-env-loader
pip install -e ".[dev]"

Testing

# Run unit tests
pytest

# Run full demo/integration tests
./examples/demo.sh

# Run CI-safe tests
./examples/demo.sh --ci

# Test coverage
pytest --cov=encrypted_env_loader

Code Quality

black src tests
isort src tests  
flake8 src tests
mypy src

License

MIT License - see LICENSE file.

Contributing

  • Fork the repository
  • Create a feature branch
  • Add tests for new functionality
  • Ensure all tests pass
  • Submit a pull request

Changelog

0.2.0

  • Keyring integration for secure local key storage
  • Automatic git repo detection for keyring service naming
  • Key resolution priority: explicit key → keyring → environment variable
  • New CLI command group: keyring with set-key, get-key, delete-key, list-keys
  • Enhanced commands: All file operations support --no-keyring flag
  • Improved status reporting: Shows key source (keyring vs environment variable)
  • Python API extensions: All functions support use_keyring parameter
  • Production/CI compatibility: Graceful fallback to environment variables

0.1.0

  • Initial release
  • Basic encryption/decryption functionality
  • CLI with all core commands
  • Python API with context managers and decorators
  • Profile support
  • Shell integration
  • CI/CD safety features with quiet modes and secret masking

Keywords

environment

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts