Show HN: REP – build-once, run anywhere. Secure runtime config for web apps(rep-protocol.dev)
rep-protocol.dev
Show HN: REP – build-once, run anywhere. Secure runtime config for web apps
https://rep-protocol.dev/
1 comments
Really like the three-tier classification (PUBLIC/SENSITIVE/SERVER). That's a thoughtful design — most env var solutions treat everything as equally secret or equally public.
The frontend injection problem you're solving is the mirror image of what we deal with on the backend side. We built KeyEnv (keyenv.dev) to handle the server-side piece: secrets stored encrypted, pulled via CLI, and injected as env vars at runtime. No .env files on disk.
The combination is interesting — REP for the browser-facing config, something like KeyEnv for the server-side secrets that feed REP_SERVER_* vars. The HMAC integrity check on the payload is a nice touch, especially for SPAs where someone could tamper with the injected HTML before it hits the client.
One question on the SENSITIVE tier: with the session-key-based decryption, what's the lifecycle of the session key? Is it per-page-load, per-user-session, or something else? That seems like the main variable in the security tradeoff.
The frontend injection problem you're solving is the mirror image of what we deal with on the backend side. We built KeyEnv (keyenv.dev) to handle the server-side piece: secrets stored encrypted, pulled via CLI, and injected as env vars at runtime. No .env files on disk.
The combination is interesting — REP for the browser-facing config, something like KeyEnv for the server-side secrets that feed REP_SERVER_* vars. The HMAC integrity check on the payload is a nice touch, especially for SPAs where someone could tamper with the injected HTML before it hits the client.
One question on the SENSITIVE tier: with the session-key-based decryption, what's the lifecycle of the session key? Is it per-page-load, per-user-session, or something else? That seems like the main variable in the security tradeoff.
Every frontend framework bakes environment variables into the JavaScript bundle at build time (process.env, import.meta.env). This means your Docker image is environment-specific — you build one for staging, another for prod, and the image you tested is never the one you deploy.
I built REP (Runtime Environment Protocol) to fix this. It's a lightweight Go gateway (~6MB binary, zero deps) that sits in front of your static file server and injects env vars into HTML responses at container startup.
What makes it different from the dozens of window.__ENV__ hacks:
- Three-tier security classification: REP_PUBLIC_* (plaintext), REP_SENSITIVE_* (AES-256-GCM encrypted, decrypted via short-lived session key), REP_SERVER_* (never reaches the browser)
- Automatic secret detection — scans PUBLIC vars for high-entropy strings, AWS keys, JWTs, etc. and refuses to start in strict mode
- HMAC integrity verification on every payload
- Optional hot config reload via SSE
- Works with any SPA (React, Vue, Svelte, Angular, vanilla) — no build tool plugins
- FROM scratch compatible — the binary is all you need
The SDK is ~1.5KB gzipped and gives you synchronous access (rep.get('API_URL')) for public vars and async decryption (await rep.getSecure('KEY')) for sensitive ones.
Full RFC-style spec, security threat model, and reference implementation: https://rep-protocol.dev
I'd especially love feedback on the security model — I've tried to be honest about what the SENSITIVE tier actually protects against vs what it doesn't. The threat model doc doesn't pretend browser-side encryption is bulletproof.
Built this because I got tired of watching every team I've worked with reinvent the same env.sh → window.__ENV__ hack with zero security thought behind it.