Security Model
How share-env encrypts and transmits .env files without the relay server ever learning the decryption key — and what guarantees that provides.
Encryption flow
push.All of the following steps occur on the sender's machine before any network connection is made.
crypto.randomBytes(32) generates 32 bytes (256 bits) of cryptographically secure randomness. This key never leaves the local process — it is embedded in the share code only.
const key = crypto.randomBytes(32); // 256-bit AES key
crypto.randomBytes(12) generates 12 bytes (96 bits) — the NIST-recommended IV size for GCM mode. A fresh IV is generated for every push, even with the same key.
const iv = crypto.randomBytes(12); // 96-bit GCM IV
The raw .env contents are encrypted. GCM mode produces both the ciphertext and a 128-bit authentication tag. The auth tag is used at decryption time to verify the ciphertext was not tampered with.
const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
const authTag = cipher.getAuthTag(); // 128-bit auth tagThe relay server receives the ciphertext + IV + authTag via POST. The key is never sent. The relay cannot decrypt anything it stores.
// What goes to the relay:
POST /push { ciphertext, iv, authTag }
// What NEVER goes to the relay:
// { key }The relay returns a 3-word identifier (phrase). The CLI appends the 64-character hex key after a # separator to form the complete share code.
const shareCode = `${phrase}#${key.toString("hex")}`;
// e.g.: apple-brave-cloud#a3f9b2c1d4e5...Relay server
CiphertextEncrypted bytes. Unreadable without the key.IV (nonce)Required for decryption, but harmless without the key.Auth tagUsed to verify integrity. Cannot be reversed to reveal plaintext.Encryption keyStays in local memory and the share code only.Plaintext .env contentsNever transmitted in cleartext at any point.Key derivation materialNo KDF, no passphrase — the full key is embedded in the share code.Threat model
| Threat | Mitigation | Status |
|---|---|---|
| Relay server is compromised | Attacker only obtains AES-256-GCM ciphertext. No key means no decryption — the ciphertext is computationally indistinguishable from random noise. | Fully mitigated |
| Share code intercepted in transit | The share code contains the decryption key — treat it like a password. Send it over an encrypted channel (Slack, Signal, Teams). Use Signal or E2EE channels for highest assurance. | User responsibility |
| Payload pulled by wrong person | The payload is deleted on first pull. If an attacker pulls first, the intended receiver gets a 404 error and should ask the sender to push again. | Burn-after-reading |
| Payload never pulled (abandoned) | The relay server automatically expires and permanently deletes all payloads after 10 minutes (600 seconds TTL), regardless of whether they were pulled. | Auto-expiry |
| Accidental git add .env | The git guardrail check blocks both push and pull from running if .gitignore does not explicitly ignore .env and .env.* files. This is mandatory and cannot be disabled. | Mandatory block |
| Ciphertext tampering in transit | AES-256-GCM produces a 128-bit authentication tag. Any bit-level modification to the ciphertext causes decryption to throw an error — tampered data is always rejected. | Auth tag verification |
| Malformed .env file | The push command validates all lines in the .env file before encrypting. Lines not matching KEY=VALUE format cause the tool to exit with an error before any upload. | Pre-upload validation |
Security Q&A