Secret-keystore – KMS-encrypted .env that never touches process.env

faiz_ahmed1 pts0 comments

@faizahmed/secret-keystore - npm

npm

Search<br>Sign UpSign In

@faizahmed/secret-keystore

1.1.0 • Public • Published 3 hours ago<br>Readme<br>Code Beta<br>4 Dependencies<br>0 Dependents<br>1 Versions<br>secret-keystore

A secure secrets management library for Node.js applications using AWS KMS encryption.

Available on npm: @faizahmed/secret-keystore

Design principle: the only thing a developer ever handles is a KMS Key ID — which is not a secret. No private keys, no passphrases, no key material. AWS KMS holds all key material server-side and authorizes access via IAM, and decrypted values live only in memory (never in process.env, never on disk) to keep the blast radius of any RCE as small as possible.

Table of Contents

Features

Important Limitations

Prerequisites

Installation

From npm Registry

Local Development / Docker Builds

Optional: YAML Support

Quick Start

CLI Reference

Library API

Runtime Keystore

Zero-Config Loader: config()

Configuration Options

How It Works

Examples

Nitro Enclave Attestation

Error Handling

TypeScript Support

Troubleshooting

Development

Security

Features

Multi-Format Support — Encrypt secrets in .env, JSON, and YAML files

Zero-Config Loader — config() discovers and cascades your .env files, decrypts them, and loads everything into an in-memory keystore in one call

Encrypt & Decrypt CLI — Full command-line round-trip (encrypt and decrypt)

Pattern Matching — Use glob patterns (**) to select keys at any depth

AWS KMS Encryption — Supports symmetric and asymmetric (RSA) keys; uses envelope encryption for RSA (no plaintext size limit)

Key-ID-Only — Developers only ever share a non-secret KMS Key ID; no key material to leak

IAM Role by Default — Uses IAM roles for authentication (explicit credentials require opt-in)

Secure In-Memory Storage — Decrypted values stored with AES-256-GCM encryption in memory

Never in process.env — Decrypted secrets are only accessible via the keystore API

TTL & Auto-Refresh — Automatic secret expiry and re-decryption

Nitro Enclave Attestation — Full attestation lifecycle with automatic 5-minute refresh

Dual API — Content-based (convenient) + Object-based (flexible)

Comment Preservation — Preserves comments and formatting in config files

Security-First Dependencies — Minimal dependencies for security-sensitive operations

Battle-Tested — Offline test suite (node:test, mocked KMS) with CI across Node 18/20/22, plus lint, format, and type-definition checks

Important Limitations

⚠️ This library is for SERVER-SIDE use only. It will NOT work with client-side code.

❌ Does NOT Work With

Scenario<br>Reason

Next.js NEXT_PUBLIC_* variables<br>These are embedded into client-side JavaScript at build time and exposed to browsers. Browsers cannot access AWS KMS.

Next.js Client Components<br>Client components run in the browser, which has no access to AWS KMS or server-side Node.js APIs.

NestJS with Client-Side Rendering<br>Any code that runs in the browser cannot decrypt KMS-encrypted values.

React/Vue/Angular frontend apps<br>Frontend JavaScript runs in users' browsers, not on servers with AWS access.

Static Site Generation (SSG) at build time<br>Build-time secrets would be embedded in static HTML/JS, defeating the purpose.

Why These Don't Work

┌─────────────────────────────────────────────────────────────────────────────┐<br>│ CLIENT-SIDE (Browser) │<br>│ │<br>│ ❌ No AWS credentials │<br>│ ❌ No access to AWS KMS API │<br>│ ❌ No Node.js crypto module │<br>│ ❌ NEXT_PUBLIC_* variables are bundled into JS at BUILD time │<br>│ ❌ Cannot make authenticated AWS API calls │<br>│ │<br>└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐<br>│ SERVER-SIDE (Node.js) │<br>│ │<br>│ ✅ Has AWS IAM role or credentials │<br>│ ✅ Can call AWS KMS Decrypt API │<br>│ ✅ Has Node.js crypto module │<br>│ ✅ Secrets decrypted at RUNTIME in memory │<br>│ ✅ Values never sent to browser │<br>│ │<br>└─────────────────────────────────────────────────────────────────────────────┘

✅ Works With

Scenario<br>Example

Next.js API Routes<br>src/app/api/*/route.ts

Next.js Server Components<br>Components without "use client"

Next.js Server Actions<br>Functions with "use server"

NestJS Services<br>Backend services running on Node.js

Express/Fastify APIs<br>Any Node.js backend

AWS Lambda<br>Serverless functions

Background Jobs<br>Cron jobs, workers, etc.

Next.js Example: What Works vs What Doesn't

// ❌ WRONG: Client Component - will NOT work<br>"use client";<br>import { getSecret } from "@/lib/keystore";

export function ClientComponent() {<br>// This will fail - browsers can't access AWS KMS<br>const secret = await getSecret("API_KEY"); // ❌ Error!<br>return div>{secret}/div>;

// ❌ WRONG: NEXT_PUBLIC_* variables - CANNOT be encrypted<br>// These are embedded in client JS at build time<br>const apiKey = process.env.NEXT_PUBLIC_API_KEY; // Already exposed to browser!

// ✅ CORRECT: API Route (Server-Side)<br>// src/app/api/data/route.ts<br>import { getSecret } from...

secret client keystore node side server

Related Articles