sealed-env
sealed-env

Encrypt your .env.
Unseal it at deploy.

A cross-stack (Node + Java / Spring Boot) library for encrypted-at-rest secrets, with optional TOTP-bound unsealing for production deploys. Built against the supply-chain attacks that broke 2024–2026.

The problem

Plaintext .env didn't survive 2024–2026.

Shai-Hulud npm worm Nov 2025

A self-replicating worm in the npm ecosystem scanned dev machines and CI runners for .env files and exfiltrated them to public GitHub repos. Thousands of credentials leaked.

tj-actions/changed-files Mar 2025

A popular GitHub Action was compromised. Every job using it dumped its environment variables into public CI logs. The blast radius reached tens of thousands of repos.

GhostAction campaign 2024–2025

A coordinated wave of stolen CI tokens used to publish trojaned packages and harvest more secrets — leveraging the very tokens most teams keep next to their .env.

The pattern is the same: read access to the file system or to the process environment becomes total credential access. Encrypting at rest is not enough — if the master key leaks alongside the file, the vault opens.

The solution

Three modes. You pick the threat model.

basic

For solo devs and private repos.

  • AES-256-GCM
  • scrypt / Argon2id KDF
  • Master key only

Defends against: backup leaks, accidental git pushes, heap dumps after key wipe.

team

For shared repos and CI.

  • Everything in basic
  • + HMAC-SHA256 integrity
  • + Independent signing key

Defends against: insider tampering, master-key-only compromise (HMAC fails before decryption attempt).

enterprise

For production deploys.

  • Everything in team
  • + Short-lived TOTP unseal token (RFC 6238)
  • + Deploy-bound challenge (commit SHA)

Defends against: compromised CI steps, captured tokens replayed against another deploy, AitM phishing of the operator.

See the decryption pipeline per mode
   basic                    team                     enterprise
   ─────                    ────                     ──────────

   .env.sealed              .env.sealed              .env.sealed
        │                        │                        │
        ▼                        ▼                        ▼
   ┌─────────┐              ┌─────────┐              ┌─────────┐
   │ AES-GCM │              │  HMAC   │              │  HMAC   │
   │ decrypt │              │ verify  │              │ verify  │
   └────┬────┘              └────┬────┘              └────┬────┘
        ▼                        ▼                        ▼
   plaintext                ┌─────────┐              ┌─────────┐
                            │ AES-GCM │              │  TOTP   │
                            │ decrypt │              │  token  │
                            └────┬────┘              │ verify  │
                                 ▼                   └────┬────┘
                            plaintext                     ▼
                                                     ┌─────────┐
                                                     │ deploy  │
                                                     │  bind   │
                                                     └────┬────┘
                                                          ▼
                                                     ┌─────────┐
                                                     │ AES-GCM │
                                                     │ decrypt │
                                                     └────┬────┘
                                                          ▼
                                                     plaintext

30-second tour

Same file. Two stacks.

A .env.sealed file written by the Node CLI decrypts cleanly from a Java / Spring Boot service, and vice versa. Verified byte-for-byte by automated cross-stack interop tests on every commit.

Node npm install sealed-env
// 1. seal your existing .env (CLI)
$ SEALED_ENV_KEY=$(openssl rand -hex 32) \
    npx sealed-env seal .env
// → writes .env.sealed (commit this)

// 2. read at startup
import { loadSealed } from "sealed-env";
loadSealed();
console.log(process.env.API_KEY);
Java / Spring Boot 3 io.github.davidalmeidac:sealed-env-spring-boot-starter
// application.yml
sealed-env:
  enabled: true
  path: .env.sealed
  fail-fast: true

// in any bean — values arrive decrypted
@Value("${API_KEY}")
private String apiKey;

Threat model

What we defend against — and what we don't.

A security tool without a published threat model is marketing. Ours is here, mapping each defense to a real 2024–2026 incident.

Attack class Defended by
Shai-Hulud npm worm (env exfil)basic
Backup leak / public S3basic
Spring Boot heapdump CVEsbasic (key wiped after derivation)
Insider tamper of .env.sealedteam
tj-actions / GhostAction CI compromiseenterprise + CHALLENGE-BIND
TOTP AitM phishing (EvilProxy)enterprise + CHALLENGE-BIND (partial)
Compromised production host with shellOut of scope (no defense possible at runtime)
Compromised KMS / operator laptopOut of scope (v0.3.x: HSM-backed keys)

Help build it

This is v0.1.0-alpha. Lots to do.

sealed-env is built openly in the Caribbean coast of Colombia. It's MIT licensed and there is no company behind it — yet. Right now it needs people who care about three things:

¿Hablas español? Soy David Almeida, dev backend autodidacta en Bucaramanga. Escríbeme en davidalmeidac@proton.me o por GitHub. Buscando feedback técnico, colaboradores, y eventualmente un equipo.