Skip to content

fix: close CRON_SECRET fail-open auth in check-renders + sponsor-outreach#605

Merged
codercatdev merged 1 commit intodevfrom
fix/cron-auth-fail-close
Mar 5, 2026
Merged

fix: close CRON_SECRET fail-open auth in check-renders + sponsor-outreach#605
codercatdev merged 1 commit intodevfrom
fix/cron-auth-fail-close

Conversation

@codercatdev
Copy link
Contributor

Security Fix: CRON_SECRET Fail-Open Auth Vulnerability

The Bug

Both check-renders and sponsor-outreach cron routes had an auth check of the form:

const authHeader = request.headers.get('authorization');
if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {

When CRON_SECRET is not set in the environment, process.env.CRON_SECRET evaluates to undefined, making the comparison string "Bearer undefined". An attacker who knows this pattern can bypass authentication entirely by sending:

Authorization: Bearer undefined

This is a fail-open vulnerability — a missing env var silently disables auth instead of blocking requests.

The Fix

Both files now follow the same fail-close pattern already used in check-research and ingest routes:

const cronSecret = process.env.CRON_SECRET;
if (!cronSecret) {
  console.error('[PIPELINE] CRON_SECRET not configured');
  return Response.json({ error: 'Server misconfigured' }, { status: 503 });
}
const authHeader = request.headers.get('authorization');
if (authHeader !== `Bearer ${cronSecret}`) {

Key changes:

  1. Extract process.env.CRON_SECRET into a const cronSecret variable
  2. Check !cronSecret before the comparison — returns 503 if not configured (fail-closed)
  3. Use cronSecret in the comparison instead of process.env.CRON_SECRET

Files Changed

  • app/api/cron/check-renders/route.ts — uses [PIPELINE] log prefix, Response.json() format
  • app/api/cron/sponsor-outreach/route.ts — uses [SPONSOR] log prefix, new Response() format

Verification

grep -n "cronSecret" app/api/cron/check-renders/route.ts app/api/cron/sponsor-outreach/route.ts

TypeScript check is clean (pre-existing @vercel/analytics type errors are unrelated to this change).

…each

When CRON_SECRET env var is undefined, the auth check compared against
'Bearer undefined' — an attacker could bypass auth by sending that header.

Now checks !cronSecret first and returns 503 if not configured, matching
the pattern already applied to check-research and ingest routes.
@vercel
Copy link

vercel bot commented Mar 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
codingcat-dev Building Building Preview, Comment Mar 5, 2026 3:29am

@codercatdev codercatdev merged commit 2ac61b4 into dev Mar 5, 2026
1 of 3 checks passed
@codercatdev codercatdev deleted the fix/cron-auth-fail-close branch March 5, 2026 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant