Stop committing .env files. Stop hoping a leak doesn't happen.
A cross-stack, zero-trust secret management library for Node.js and Java/Spring Boot โ with optional TOTP-based unsealing for production deploys.
Docs ยท Threat Model ยท File Format ยท Security Policy ยท Landing
In 2025 alone, supply-chain attacks on the JavaScript ecosystem stole thousands of
plaintext secrets from CI/CD pipelines and developer machines. The Shai-Hulud worm
(November 2025) compromised over 25,000 repositories by scanning for .env files
and exfiltrating their contents to public GitHub repos. On May 12, 2026, TeamPCP
open-sourced the full framework on GitHub; clones appeared within 48 hours.
The lesson is simple: plaintext .env is dead. And encrypted-at-rest alone isn't
enough โ if the master key leaks (and they do โ see the tj-actions and GhostAction
campaigns), the entire vault opens.
sealed-env solves both halves: it encrypts your secrets at rest, and it can require
a fresh TOTP code from a human operator before each production deploy. Even if your CI
pipeline is fully compromised, attackers cannot decrypt without the operator's phone.
Honest scope claim: sealed-env reduces the impact of Shai-Hulud-class supply-chain attacks by keeping master keys out of disk and
process.envwhen configured withsealed-env keychain pushand enterprise mode + short-TTL unseal tokens. It does not prevent the initial compromise of a developer machine or CI runner. Full per-module analysis:threat-research/analysis/shai-hulud-defense.md. Runsealed-env doctorfor an automated posture check.
- A
.env.sealedfile format that's identical across Node and Java. Mix stacks freely. - Three security modes the user picks:
basicfor dev,teamfor staging,enterprisefor production with TOTP unseal. - Zero runtime dependencies in the Node package. Only Node's built-in
cryptoandfs. - A published threat model that says exactly what we defend against and what we don't.
- A CLI (
npx sealed-env) and a Spring Boot starter (Java).
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Node side โ โ Java side โ
โ โโโโโโโโโโโโ โ โ โโโโโโโโโโโโ โ
โ โข CLI: sealed-env seal โ โ โข SealedEnv core lib โ
โ โข npm: sealed-env โ โ โข Spring Boot starter โ
โ โข writes KDF=scrypt โ โ โข writes KDF=argon2id โ
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโ โโโโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ โ
โ both speak SEALED-ENV-V1 โ
โ (byte-for-byte spec compliance) โ
โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ .env.sealed โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ SEALED-ENV-V1 MODE=team โ
โ KDF=<scrypt|argon2id> โ
โ KDF-PARAMS=... SALT=... โ
โ NONCE=... AAD-DIGEST=... โ
โ HMAC=... CREATED=2026-... โ
โ โ
โ <base64 ciphertext + GCM tag> โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โฒ โฒ
โ a file written by one โ
โ stack decrypts in the โ
โ other โ no conversion โ
โ โ
โโโโโโโโโโโโโโดโโโโโโโโโโโโโ โโโโโโโโโโโโโโดโโโโโโโโโโโโโ
โ Node app reads it โ โ Java app reads it โ
โ (loadSealed()) โ โ (Spring Environment) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
From 0.2.1 onwards, every npm release ships with SLSA Build Level 3
provenance signed via Sigstore through GitHub Actions trusted
publishing. After installing, you can confirm that the tarball was
built from the source we publish (not from a compromised pipeline):
npm audit signatures sealed-envExpect output that includes verified for sealed-env with a
signature link to a Sigstore transparency log entry. If the command
reports anything else, do not run sealed-env โ open an issue first.
This is a real check, not a marketing pixel: the TanStack supply-chain
attack of May 2026 published malicious packages with valid-looking
SLSA Build Level 3 provenance, so provenance alone is insufficient.
But combined with version pinning + release-age cooldowns (pnpm 11 minimumReleaseAge: 24h or yarn npmMinimalAgeGate: 3d), it's a
meaningful defensive layer.
# 1. Install
npm install sealed-env
# 2. Initialize a vault for your project
npx sealed-env init
# โ generates a master key (saved locally to .env.local, gitignored)
# โ if you choose 'enterprise' mode, also displays a QR code for your authenticator
# 3. Encrypt your existing .env
npx sealed-env encrypt .env
# โ creates .env.sealed (commit this!)
# 4. Use it in code โ no API change
import 'sealed-env/config';
console.log(process.env.STRIPE_API_KEY); // works as if it were a normal .env<dependency>
<groupId>io.github.davidalmeidac</groupId>
<artifactId>sealed-env-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency># application.yml
sealed-env:
file: .env.sealed
key-source: env@Value("${stripe.api.key}") // resolved transparently from .env.sealed
private String stripeKey; 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 โ
โ master_key โ + signing_key โ bind โ
โโโโโโฌโโโโโ
โผ
โโโโโโโโโโโ
โ AES-GCM โ
โ decrypt โ
โโโโโโฌโโโโโ
โผ
plaintext
โฒ
โ + unseal token (carries
โ salt-bound TOTP epoch)
โ + deploy_id
| basic | team | enterprise | |
|---|---|---|---|
| AES-256-GCM cipher | โ | โ | โ |
| Argon2id key derivation | โ | โ | โ |
| HMAC integrity tag | โ | โ | โ |
| TOTP unseal required | โ | โ | โ |
| Deploy-bound unseal tokens | โ | โ | โ |
| Replay protection | โ | โ | โ |
| Memory wipe after read | โ | โ | โ |
Host-side decrypt (deploy --remote) |
โ | โ | โ |
| Suitable for | personal projects | staging, small teams | production, fintech, PII |
Pick the one that fits your threat model. Upgrade later with one command:
npx sealed-env upgrade --to enterpriseโโโโโโโโโโโโโโโโ 1. push โโโโโโโโโโโโโโโโ
โ developer โ โโโโโโโโโโโโถ โ github โ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ 2. CI runs
โผ
โโโโโโโโโโโโโโโโ
โ CI pipeline โ paused, waiting for unseal
โโโโโโโโโโโโโโโโ
โ
โ 3. notifies operator
โผ
โโโโโโโโโโโโโโโโ
โ operator โ 4. opens authenticator app,
โ (you) โ reads 6-digit TOTP code
โโโโโโโโโโโโโโโโ
โ
โ 5. runs:
โ sealed-env unseal --totp 482914 \
โ --deploy-id <commit-sha>
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ unseal token (60s lifetime, bound to โ
โ this specific deploy) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 6. paste into CI form
โผ
โโโโโโโโโโโโโโโโ
โ deploy runs โ decrypts .env.sealed
โ to prod โ with master_key + token
โโโโโโโโโโโโโโโโ
If the master key leaks AFTER the deploy โ attacker still needs the operator's
TOTP. If the TOTP token leaks โ useless for the next deploy (different commit).
The honest version. Different tools for different threat models โ pick the one that matches yours.
| sealed-env | dotenv | dotenvx | Doppler | HashiCorp Vault | AWS Secrets Manager | jasypt | |
|---|---|---|---|---|---|---|---|
| Encryption at rest | โ | โ plaintext | โ | โ | โ | โ | โ |
| Cross-stack (Node + Java) | โ same wire format | n/a | Node only | language-agnostic (HTTP) | language-agnostic (HTTP) | language-agnostic (HTTP) | Java only |
| No external service required | โ | โ | โ | โ paid SaaS | โ self-hosted server | โ AWS | โ |
| TOTP unseal at deploy time | โ | โ | โ | โ | โ | โ | |
| Replay protection (deploy-bound tokens) | โ | โ | โ | โ | โ | โ | |
| Public threat model | โ | n/a | partial | NDA only | โ | โ | โ |
| Zero runtime dependencies (Node) | โ | โ | โ (8+ deps) | โ SDK | โ SDK | โ SDK | n/a |
| Spring Boot autoconfiguration | โ | n/a | n/a | community | community | community | manual |
| Memory wipe after key derivation | โ | n/a | โ | โ | โ | โ | โ |
| License | MIT | MIT | MIT | proprietary | MPL 2.0 | proprietary | Apache 2.0 |
| Cost | free | free | free | $0โ$15/user/mo | free / Enterprise $ | $0.40/secret/mo | free |
dotenvโ solo dev, dev environment only, never production. Fine.dotenvxโ Node-only project, encryption at rest is enough, you trust your CI keystore. Fine.Doppler/AWS Secrets Managerโ you already pay for the platform, comfortable with vendor lock-in, want centralized rotation across many services. Good.HashiCorp Vaultโ you have ops capacity to run a Vault cluster, need fine-grained policies, and dynamic secrets (DB credentials per session). Heavy but powerful.jasyptโ Java-only project, encryption at rest is enough, you don't need cross-stack. Fine.sealed-envโ you want encryption at rest + a hard floor against compromised CI/CD (TOTP-bound deploys), no external service, and your stack is Node, Java/Spring Boot, or both. The defense ceiling is higher than dotenvx/jasypt; the operational cost is lower than Vault.
- Not a centralized secret manager (no rotation API, no audit log, no team policies).
- Not a substitute for HashiCorp Vault when you need dynamic per-session credentials.
- Not a fit if you want a SaaS dashboard.
If your team needs the Doppler/Vault feature set, use them. sealed-env is the right pick when you want a static, file-based, version-controllable encrypted secret with a higher security floor than dotenvx.
Pre-sealed apps you can clone and run in 60 seconds:
- ๐ฆ examples/node-express โ Node + Express server using
import 'sealed-env/config' - โ examples/spring-boot โ Java + Spring Boot 3 with the auto-config starter
The demo master key is checked in alongside each example so the apps work out of the box. It's public โ never use it in real projects.
A desktop GUI on top of sealed-env, for the people who don't live in
the terminal. Built with Tauri 2 + React + TypeScript, with its own
Rust implementation of SEALED-ENV-V1 โ the third stack alongside
Node and Java, validated against the same cross-stack test vectors.
What works today:
- Viewer โ open a
.env.sealedfile, unlock with master / signing / TOTP, browse and mask values. - Init wizard โ 5-step flow (folder โ mode โ source โ keys โ
review) for
basic,team, andenterprise. Auto-detects.env,.env.example,.env.sample,.env.template,.env.dist. QR code for enterprise authenticator pairing. Auto-appends.envto.gitignore. - Recent projects + settings panel (default mode, gitignore toggle, value masking, Argon2id parameter tuning).
Still pre-alpha โ looking for testers and contributors. The Rust core
reads files sealed by the Node CLI and Java library byte-for-byte
(validated by decrypts_node_enterprise_vector and friends in CI).
โ github.com/davidalmeidac/sealed-env-studio
โ Full documentation index โ start here if you're new.
- ๐ Overview โ what
sealed-envis and isn't - ๐ Quick start: Node
- ๐ Quick start: Java + Spring Boot
- ๐ Enterprise mode walkthrough โ TOTP + deploy binding
- ๐ ๏ธ Operational guide โ for sysadmins, managers, and founders (no code)
- โ๏ธ CI/CD + cloud recipes โ GitHub Actions, GitLab, Bitbucket, CircleCI, Jenkins, Azure, AWS, GCP, Vercel, Railway, Docker, K8s
- ๐ Project lifecycle โ init โ onboarding โ deploy as one narrative
- ๐ฏ Decrypt strategies โ host-side vs in-process trade-off
- ๐จ Incident response โ playbook for a compromised host (โ deadman switch warning)
- ๐ File format anatomy โ what's inside
.env.sealed - ๐ Format specification โ the canonical wire format (v1)
- ๐ Secret patterns โ canonical regex spec for tools like gitleaks / trufflehog
- ๐ก๏ธ Security policy โ how to report vulnerabilities
- ๐ Threat model โ which 2024-2026 attacks
sealed-envdefends against
- ๐ชฑ Shai-Hulud defensive analysis โ module-by-module mapping of TTPs to defenses
- ๐ IOC table โ consolidated indicators from public research
- ๐ฃ๏ธ Improvement roadmap โ prioritized hardening for 0.2.2 / 0.3.0
- ๐ก Future: supply-chain IOC feed bot โ design brainstorm
CVE-2026-45091 was responsibly
self-disclosed and patched in 0.1.0-alpha.4. The disclosure has been
independently indexed and analyzed by:
| Source | What it is |
|---|---|
| NIST NVD | Official US National Vulnerability Database entry (CVSS 9.1, CWE-200 + CWE-522) |
| CVE.org | Canonical CVE record |
| GitHub Security Advisory | GHSA-x3r2-fj3r-g5mv (our advisory) |
| CVEReports | Independent technical analysis by Alon Barad (Software Engineer) |
| DailyCVE | Independent technical writeup |
| CIRCL Vulnerability-Lookup | European tracking (Luxembourg CERT) |
| Sploitus | Exploit feed aggregator entry |
| HORKimhab/CVE-2026-45091 | Third-party reproducible PoC published for research |
We list these because verifiable third-party coverage is part of a healthy disclosure track-record. The CVE itself is a fixed bug, not a current defect โ see the advisory for the full timeline and remediation steps.
v0.1.0 โ stable. The wire format (SEALED-ENV-V1) is frozen and
will remain readable forever. The public API is stable. Bug-fix and
non-breaking feature releases land as 0.1.x; breaking changes wait
for 0.2.0.
What's in 0.1.0:
- Three modes:
basic,team,enterprise(TOTP-bound deploys) - Node CLI (
init,encrypt,decrypt,get/set/edit/diff,exec,deploy,keychain) -
deploy --remotefor Model A host-side decrypt deploys - Cross-stack: Node + Java libraries reading the same wire format
- Spring Boot 3 starter (auto-config +
@Valuesupport) - OS keychain backend (Windows DPAPI, macOS Keychain, Linux secret-tool)
- 17 platform CI/CD recipes including OIDC federation
- Cryptographic test vectors validated cross-stack in CI
Roadmap:
- v0.1.x โ
sealed-env doctor+install-hooks+ library-side.env.localautoload (non-breaking) - v0.2.0 โ Java CLI (Maven-distributed) ยท Shamir Secret Sharing ยท sidecar pattern
- v0.3.0 โ
memfd_secretLinux memory protection ยท heap-dump filter - v1.0 โ Hardware-backed wrapping (TPM / Secure Enclave / YubiKey)
Companion projects:
- sealed-env-studio โ desktop GUI (Tauri + React + Rust), Phase 1 viewer + Phase 2 init wizard implemented, cross-stack interop validated, pre-alpha
This is a security-sensitive project. Contributions are very welcome but please read SECURITY.md first. Crypto changes require explicit discussion.
MIT โ David Almeida, 2026.
"Encrypt at rest. Authenticate at deploy. Wipe on read."