npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

secure-env-vars

v2.0.0

Published

Zero-cloud encrypted .env vaults by Cortlet.

Readme

⚡ secure-env-vars

Secure Env Vars v2 — zero-cloud encrypted .env vaults using local RSA identities.

No account. No hosted service. No secret dashboard. No internet required.

secure-env-vars lets you encrypt a plaintext .env file into a shareable .env.vault, then safely inject the decrypted secrets into a process at runtime.

secure-env-vars run node app.js

Why secure-env-vars?

Most secret managers depend on cloud accounts, hosted workspaces, or centralized dashboards.

secure-env-vars is different:

  • Zero cloud — secrets stay local.
  • RSA identity based — access is granted through public keys.
  • Team sharing — allow teammates without sharing private keys.
  • Memory injection — run commands with secrets in process.env.
  • No plaintext required at runtime.env.vault is enough.
  • V2 vault format — authenticated AES-256-GCM payloads with RSA-OAEP key wrapping.
  • Migration support — migrate older v1 vaults to v2.
  • Key rotation — rotate vault encryption keys safely.

Part of the Cortlet software brand.


Install

Use directly with npx:

npx secure-env-vars --help

Or install globally:

npm install -g secure-env-vars

Then use either command name:

secure-env-vars --help

or:

env-vault --help

Quick Start

1. Initialize a project

secure-env-vars init

This creates a starter .env if one does not already exist and updates .gitignore.

Example:

EXAMPLE_SECRET=change-me

2. Lock your .env

secure-env-vars lock

This encrypts .env into .env.vault.

The vault can be committed to git. The plaintext .env should not be committed.

3. Run your app with secrets injected

secure-env-vars run node app.js

Or with separator syntax:

secure-env-vars run -- node app.js

Both forms are supported.

Your app receives decrypted values through environment variables:

console.log(process.env.EXAMPLE_SECRET);

The plaintext .env does not need to exist at runtime.


RSA Identity

secure-env-vars uses your local RSA identity.

By default, it looks for keys in:

~/.ssh/

Common supported key names include:

id_rsa
id_rsa.pub

If you do not have RSA keys, generate a local RSA identity:

node -e "const crypto = require('node:crypto'); const fs = require('node:fs'); const path = require('node:path'); const os = require('node:os'); const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', { modulusLength: 4096, publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' } }); const sshDir = path.join(os.homedir(), '.ssh'); if (!fs.existsSync(sshDir)) fs.mkdirSync(sshDir, { recursive: true }); fs.writeFileSync(path.join(sshDir, 'id_rsa'), privateKey); fs.writeFileSync(path.join(sshDir, 'id_rsa.pub'), publicKey); console.log('Identity created at ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub');"

Keep your private key private.


Team Access

Add a teammate using their public key:

secure-env-vars allow ./teammate_id_rsa.pub --label "Teammate"

List authorized identities:

secure-env-vars list

Revoke access:

secure-env-vars revoke "Teammate"

You can also revoke by fingerprint:

secure-env-vars revoke SHA256:exampleFingerprintHere

revoke removes an identity from future vault access. For stronger security after removing someone, rotate the vault key.

secure-env-vars rotate

Key Rotation

Rotate the vault encryption key:

secure-env-vars rotate

This:

  1. Creates a backup.
  2. Decrypts the current vault using your identity.
  3. Generates a new AES vault key.
  4. Re-encrypts the payload.
  5. Re-wraps the new key for allowed identities.
  6. Writes the updated .env.vault.

For older v2 vaults that do not store teammate public keys, use:

secure-env-vars rotate --current-only

Then re-add teammates:

secure-env-vars allow ./teammate_id_rsa.pub --label "Teammate"

Migration from v1 to v2

Migrate an older v1 vault:

secure-env-vars migrate

The migration command creates a backup first:

.env.vault.backup-...

Then it rewrites .env.vault using the v2 format.

After migration, verify:

secure-env-vars status
secure-env-vars run node app.js

Only the current identity is preserved during v1 migration. Re-run allow for teammates.


Health Checks

Check project status:

secure-env-vars status

Run diagnostics:

secure-env-vars doctor

Scan for plaintext secrets or risky env files:

secure-env-vars scan

Commands

| Command | Description | |:--|:--| | init | Initialize project files and .gitignore. | | lock | Encrypt .env into .env.vault. | | unlock | Decrypt vault contents into a plaintext output file. | | run | Run a command with vault secrets injected into memory. | | allow | Add a public key identity to the vault. | | list | List identities authorized for the vault. | | revoke | Remove an identity from the vault. | | status | Show vault/project status. | | doctor | Run project and vault diagnostics. | | scan | Scan for plaintext env files and secret-like values. | | migrate | Convert older v1 vaults to v2. | | rotate | Rotate the vault encryption key. |


Examples

Lock default .env

secure-env-vars lock

Use a custom vault path

secure-env-vars lock --env .env --vault production.vault

Run with that custom vault:

secure-env-vars run --vault production.vault node app.js

Unlock to a temporary file

secure-env-vars unlock --out .env.unlocked

Print decrypted env content

secure-env-vars unlock --print

Be careful with --print; it writes secrets to the terminal.


What gets committed?

Usually commit:

.env.vault

Do not commit:

.env
.env.local
.env.*.local
.env.unlocked

secure-env-vars init helps update .gitignore.


Security Model

secure-env-vars uses envelope encryption:

  1. A random AES-256 key encrypts the .env payload.
  2. The payload is encrypted with AES-256-GCM.
  3. The AES key is wrapped for each allowed RSA public key.
  4. Each authorized identity can unwrap the AES key using its private key.
  5. Secrets are injected into the child process environment during run.

Private keys are never stored in the vault.


V2 Vault Format

A v2 vault contains:

{
  "version": 2,
  "product": "Cortlet Env Vault",
  "createdAt": "...",
  "updatedAt": "...",
  "identities": [
    {
      "id": "...",
      "label": "...",
      "publicKeyFingerprint": "SHA256:...",
      "publicKeyPem": "-----BEGIN PUBLIC KEY-----...",
      "wrappedKey": "...",
      "addedAt": "..."
    }
  ],
  "payload": {
    "iv": "...",
    "tag": "...",
    "data": "..."
  }
}

The payload is authenticated. If the wrong key is used or the vault is modified incorrectly, decryption fails.


Development

Install dependencies:

npm install

Build:

npm run build

Run unit tests:

npm run test:unit

Run all tests:

npm test

Package dry run:

npm pack --dry-run

Current Test Coverage

The v2 test suite covers:

  • crypto encryption/decryption
  • strict base64 validation
  • .env parsing
  • v2 vault format validation
  • vault service lock/decrypt/unlock
  • init
  • allow
  • revoke
  • run
  • migrate
  • rotate
  • scan
  • doctor

Design Philosophy

secure-env-vars is built for developers who want secret management without surrendering control to a hosted service.

The goal is simple:

local keys
local vaults
safe sharing
no cloud dependency
no bloat

License

MIT


Built for the sovereign developer.
Part of the Cortlet software brand.