fail closed when PUBLIC_BUILD_ENV is unset

Origin validation, every rate limiter and the password-strength check each
treated an unset PUBLIC_BUILD_ENV as "relaxed", so a deployment that forgot the
variable silently ran with CORS reflecting any origin, no brute-force limit on
the sole account, and no password rules. setup.sh writes it, but .env.example
never mentioned it.

The three now share IS_DEV_BUILD, which is true only when PUBLIC_BUILD_ENV is
explicitly "dev" or "development". Anything else, including unset, is hardened.
Documented in .env.example.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
brunorezio
2026-07-25 23:30:20 +01:00
co-authored by Claude Opus 5
parent 85596da086
commit 8163f04420
5 changed files with 22 additions and 19 deletions
+2 -4
View File
@@ -1,5 +1,6 @@
import type { Context, MiddlewareHandler } from 'hono';
import * as errors from '../custom-errors';
import { IS_DEV_BUILD } from '../build-env';
type RateLimitEntry = {
count: number;
@@ -24,9 +25,6 @@ function cleanupStore(store: Map<string, RateLimitEntry>) {
}
}
const { PUBLIC_BUILD_ENV } = process.env;
const isProduction = PUBLIC_BUILD_ENV === 'production' || PUBLIC_BUILD_ENV === 'staging';
export function rateLimiter(options: RateLimiterOptions): MiddlewareHandler {
const {
windowMs,
@@ -43,7 +41,7 @@ export function rateLimiter(options: RateLimiterOptions): MiddlewareHandler {
setInterval(() => cleanupStore(store), 60_000);
return async (ctx, next) => {
if (!isProduction) return next();
if (IS_DEV_BUILD) return next();
const key = keyGenerator(ctx);
const now = Date.now();