
Security News
Feross on the 10 Minutes or Less Podcast: Nobody Reads the Code
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.
@phantasm0009/secure-env
Advanced tools
End-to-end secret management with encrypted .env files, git protection, and runtime validation
🔐 End-to-end secret management for Node.js applications with encrypted .env files, git protection, and runtime validation.
.env.local, .env.production, etc.npm install @phantasm0009/secure-env
Create a .env file with your secrets:
# .env
API_KEY=your-secret-api-key-here
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
DEBUG=true
PORT=3000
# Generate encryption key and encrypt .env
npx secure-env encrypt
# This creates:
# - .env.key (keep this secret!)
# - .env.encrypted (safe to commit)
# Install pre-commit hooks and update .gitignore
npx secure-env setup-git
const { SecureEnv, envSchema, string, number, boolean } = require('@phantasm0009/secure-env');
// Define validation schema
const schema = envSchema({
PORT: number().min(3000).max(8000),
API_KEY: string().length(32),
DEBUG: boolean(),
DATABASE_URL: string().regex(/^postgresql:\/\//)
});
// Load and validate environment
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);
console.log('Validated environment:', env);
// Output: { PORT: 3000, API_KEY: 'your-secret-api-key-here', DEBUG: true, ... }
# Encrypt .env file (creates .env.encrypted and .env.key)
secure-env encrypt
# Encrypt specific file
secure-env encrypt .env.production
# Decrypt to .env
secure-env decrypt
# Decrypt to specific file
secure-env decrypt --output .env.development
# Generate new encryption key
secure-env generate-key
# Use custom key path
secure-env encrypt --key-path ./keys/production.key
# Check if required variables are present
secure-env check PORT API_KEY DATABASE_URL
# Validate against schema file
secure-env validate schema.js
# Setup git hooks and .gitignore protection
secure-env setup-git
const { SecureEnv } = require('@phantasm0009/secure-env');
const secureEnv = new SecureEnv();
// Encryption/Decryption
secureEnv.encryptFile('.env', '.env.encrypted');
secureEnv.decryptFile('.env.encrypted', '.env');
// Key management
const key = secureEnv.generateKey();
secureEnv.saveKey(key, '.env.key');
// Load with validation
const env = secureEnv.load(schema, { override: true });
// Setup git protection
secureEnv.setupGitProtection();
Build validation schemas with chainable methods:
const { envSchema, string, number, boolean } = require('@phantasm0009/secure-env');
const schema = envSchema({
// String validation
API_KEY: string()
.length(32) // Exact length
.regex(/^[a-zA-Z0-9]+$/) // Pattern matching
USERNAME: string()
.min(3) // Minimum length
.max(20), // Maximum length
// Number validation
PORT: number()
.min(3000) // Minimum value
.max(8000) // Maximum value
.int(), // Must be integer
TIMEOUT: number()
.min(0),
// Boolean validation
DEBUG: boolean(),
ENABLED: boolean()
});
const { loadEnv } = require('@phantasm0009/secure-env');
// Load with options
const env = loadEnv({
path: './config', // Directory to search
override: true, // Override existing values
debug: true // Log loaded files
});
const { validateEnv, checkRequired } = require('@phantasm0009/secure-env');
// Validate against schema
const validated = validateEnv(process.env, schema);
// Check required variables
const result = checkRequired(['API_KEY', 'DATABASE_URL']);
if (!result.valid) {
console.error('Missing:', result.missing);
}
const express = require('express');
const { SecureEnv, envSchema, string, number, boolean } = require('@phantasm0009/secure-env');
// Define schema for your app
const schema = envSchema({
PORT: number().min(3000).max(8000),
NODE_ENV: string().regex(/^(development|production|test)$/),
JWT_SECRET: string().min(32),
DATABASE_URL: string().regex(/^postgresql:\/\//),
REDIS_URL: string().regex(/^redis:\/\//),
DEBUG: boolean()
});
// Load and validate environment
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);
const app = express();
app.get('/', (req, res) => {
res.json({
message: 'Server running securely!',
environment: env.NODE_ENV,
debug: env.DEBUG
});
});
app.listen(env.PORT, () => {
console.log(`Server running on port ${env.PORT}`);
});
// next.config.js
const { SecureEnv, envSchema, string, number, boolean } = require('@phantasm0009/secure-env');
const schema = envSchema({
NEXT_PUBLIC_API_URL: string().regex(/^https?:\/\//),
DATABASE_URL: string(),
NEXTAUTH_SECRET: string().min(32),
NEXTAUTH_URL: string().regex(/^https?:\/\//),
NODE_ENV: string().regex(/^(development|production|test)$/)
});
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);
module.exports = {
env: {
CUSTOM_KEY: env.NEXT_PUBLIC_API_URL,
},
// ... other Next.js config
};
# Dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
RUN npm ci --only=production
# Copy source code
COPY . .
# Decrypt environment file during build
RUN npx secure-env decrypt --output .env
# Start application
CMD ["npm", "start"]
# Build with encrypted env file
docker build -t myapp .
# Or mount key at runtime
docker run -v $(pwd)/.env.key:/app/.env.key myapp
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Create encryption key
run: echo "${{ secrets.ENV_KEY }}" > .env.key
- name: Decrypt environment
run: npx secure-env decrypt
- name: Run tests
run: npm test
- name: Deploy
run: npm run deploy
The loader searches for environment files in this order (later files override earlier ones):
.env.env.local.env.development / .env.production / .env.test.env.development.local / .env.production.local / .env.test.local# Generate strong keys for different environments
secure-env generate-key --key-path .env.development.key
secure-env generate-key --key-path .env.production.key
# Encrypt environment-specific files
secure-env encrypt .env.development --key-path .env.development.key
secure-env encrypt .env.production --key-path .env.production.key
The git protection feature automatically:
.env* files*.key files.gitignore with secure patternsFor production environments, consider using cloud KMS:
const { createKMSProvider } = require('@phantasm0009/secure-env');
// AWS KMS
const kms = createKMSProvider('aws', {
region: 'us-east-1',
keyId: 'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'
});
// Google Cloud KMS
const kms = createKMSProvider('google', {
projectId: 'my-project',
keyRingId: 'my-keyring',
keyId: 'my-key'
});
const { SecureEnv } = require('@phantasm0009/secure-env');
try {
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);
console.log('Environment loaded successfully');
} catch (error) {
if (error.message.includes('Environment validation failed')) {
console.error('❌ Configuration errors:');
console.error(error.message);
process.exit(1);
}
if (error.message.includes('Encryption key not found')) {
console.error('❌ Missing encryption key. Run: npx secure-env generate-key');
process.exit(1);
}
throw error;
}
const schema = envSchema({
EMAIL: string().regex(
/^[^\s@]+@[^\s@]+\.[^\s@]+$/,
'Must be a valid email address'
),
API_VERSION: string().regex(
/^v\d+$/,
'Must be in format v1, v2, etc.'
),
PORT: number()
.min(1024, 'Port must be above 1024')
.max(65535, 'Port must be below 65535')
});
// Load specific environment configurations
const devEnv = loadEnv({
path: './environments/development',
debug: true
});
const prodEnv = loadEnv({
path: './environments/production',
override: true
});
const baseSchema = envSchema({
NODE_ENV: string().regex(/^(development|production|test)$/),
DEBUG: boolean()
});
const databaseSchema = envSchema({
DATABASE_URL: string().regex(/^postgresql:\/\//),
DB_POOL_SIZE: number().min(1).max(20)
});
const apiSchema = envSchema({
API_KEY: string().length(32),
API_TIMEOUT: number().min(1000)
});
// Combine schemas
const fullSchema = envSchema({
...baseSchema,
...databaseSchema,
...apiSchema
});
Run the test suite:
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run specific test file
node --test test/encryption.test.js
Q: "Encryption key not found" error
# Generate a new key
npx secure-env generate-key
# Or specify custom path
npx secure-env generate-key --key-path ./custom/path/.env.key
Q: Git hooks not working
# Reinstall git hooks
npx secure-env setup-git
# Check if .git/hooks/pre-commit exists and is executable
ls -la .git/hooks/pre-commit
Q: Validation errors
# Check which variables are missing
npx secure-env check API_KEY DATABASE_URL PORT
# Validate against schema file
npx secure-env validate ./config/schema.js
Q: Environment not loading
// Enable debug mode to see which files are loaded
const env = loadEnv({ debug: true });
git checkout -b feature/amazing-featurenpm testgit commit -m 'Add amazing feature'git push origin feature/amazing-featureMIT License - see LICENSE file for details.
For security issues, please email security@phantasm0009.dev instead of using GitHub issues.
FAQs
End-to-end secret management with encrypted .env files, git protection, and runtime validation
We found that @phantasm0009/secure-env demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

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.

Security News
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.

Research
/Security News
Campaign of 108 extensions harvests identities, steals sessions, and adds backdoors to browsers, all tied to the same C2 infrastructure.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.