Both auth.ts and trpc.ts now delegate the E2E_TEST_MODE-in-production check to a single shared helper (packages/api/src/lib/runtime-security.ts). trpc.ts used to only console.warn; it now throws at module load time, matching the behaviour already enforced by assertSecureRuntimeEnv on the auth side. A future refactor can no longer silently drop the guard on either side. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
39 lines
1.4 KiB
TypeScript
39 lines
1.4 KiB
TypeScript
/**
|
|
* Shared fail-fast checks for dev-only bypass flags.
|
|
*
|
|
* Both `apps/web/src/server/runtime-env.ts` and `packages/api/src/trpc.ts`
|
|
* gate behaviour on `E2E_TEST_MODE`. Historically each had its own check
|
|
* (one throwing, one `console.warn`-ing), which meant a refactor that
|
|
* dropped one import silently re-enabled the bypass in production. This
|
|
* module is the single source of truth; both call sites delegate here.
|
|
*
|
|
* CapaKraken security ticket #42 / EAPPS 3.2.7.04.
|
|
*/
|
|
|
|
type RuntimeEnv = Partial<Record<string, string | undefined>>;
|
|
|
|
const DEV_BYPASS_FLAGS = ["E2E_TEST_MODE"] as const;
|
|
|
|
export function isE2eBypassActive(env: RuntimeEnv = process.env): boolean {
|
|
return env["E2E_TEST_MODE"] === "true" && env["NODE_ENV"] !== "production";
|
|
}
|
|
|
|
export function getDevBypassViolations(env: RuntimeEnv = process.env): string[] {
|
|
if (env["NODE_ENV"] !== "production") return [];
|
|
const out: string[] = [];
|
|
for (const flag of DEV_BYPASS_FLAGS) {
|
|
if (env[flag] === "true") {
|
|
out.push(
|
|
`${flag} must not be 'true' in production — it disables rate limiting and session controls.`,
|
|
);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
export function assertNoDevBypassInProduction(env: RuntimeEnv = process.env): void {
|
|
const violations = getDevBypassViolations(env);
|
|
if (violations.length === 0) return;
|
|
throw new Error(`[FATAL] Dev-bypass flag set in production: ${violations.join(" ")}`);
|
|
}
|