Skip to content

fix(security): require CRON_SECRET on cron + LoTW sync endpoints#220

Merged
patrickrb merged 1 commit into
mainfrom
fix/cron-auth-hardening
Jul 13, 2026
Merged

fix(security): require CRON_SECRET on cron + LoTW sync endpoints#220
patrickrb merged 1 commit into
mainfrom
fix/cron-auth-hardening

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

Problem

Two authentication holes made the LoTW sync endpoints publicly triggerable:

  1. Trusted-host sniff. /api/cron/lotw-{upload,download} treated any request whose host contains "vercel" (or with a x-vercel-id / vercel user-agent header) as a trusted cron — on any *.vercel.app deployment the CRON_SECRET check was effectively disabled. All of these signals are caller-controlled.
  2. Spoofable X-Cron-Job header. /api/lotw/upload and /api/lotw/download skipped user auth entirely when the request carried X-Cron-Job: true — any anonymous caller could trigger uploads/downloads for any station_id.

Fix

  • New src/lib/cron-auth.tshasValidCronSecret(): strict Authorization: Bearer ${CRON_SECRET} comparison, no fallbacks.
  • Cron routes: deleted the host/UA sniff; the Bearer token is required unconditionally, and a missing CRON_SECRET fails closed (500) instead of open. (Vercel attaches the header automatically when the env var is set.)
  • LoTW upload/download routes: X-Cron-Job remains only as a mode discriminator — cron mode now additionally requires the valid Bearer token, and a cron-flagged request without it gets a 401 (never falls through to cookie auth). The cron routes' internal fetches now pass the Authorization header.
  • README: new "Scheduled sync" section documenting CRON_SECRET on Vercel and the self-hosted crontab pattern.

Verification

🤖 Generated with Claude Code

The cron routes trusted any request whose host/user-agent/x-vercel-id header
mentioned vercel, which disabled the CRON_SECRET check on every *.vercel.app
deployment. Separately, /api/lotw/{upload,download} skipped auth entirely on
a spoofable X-Cron-Job: true header, letting anonymous callers trigger
uploads/downloads for any station_id.

- New src/lib/cron-auth.ts: strict Bearer CRON_SECRET check, no fallbacks.
- Cron routes require the Bearer token unconditionally and fail closed (500)
  when CRON_SECRET is unset. Vercel attaches the header automatically when
  the env var exists.
- X-Cron-Job is now only a mode discriminator: cron mode additionally
  requires the valid Bearer token; the cron routes' internal fetches send it.
- README: "Scheduled sync" section for Vercel + self-hosted crontab setup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
nodelog Ready Ready Preview, Comment Jul 13, 2026 3:23pm

Request Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Closes two authentication bypasses that allowed anonymous callers to trigger LoTW upload/download work by spoofing Vercel/cron-related headers, and documents the required deployment configuration.

Changes:

  • Introduces a shared hasValidCronSecret() helper that strictly validates Authorization: Bearer ${CRON_SECRET} with no trusted-host/user-agent fallbacks.
  • Requires a valid Bearer token for /api/cron/lotw-{upload,download} and for cron-mode execution of /api/lotw/{upload,download} (where X-Cron-Job is now only a mode discriminator).
  • Documents scheduled sync setup for Vercel and self-hosted schedulers in the README.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/lib/cron-auth.ts Adds centralized strict Bearer-token validation for cron authentication.
src/app/api/lotw/upload/route.ts Prevents X-Cron-Job spoofing by requiring a valid cron Bearer token in cron mode.
src/app/api/lotw/download/route.ts Prevents X-Cron-Job spoofing by requiring a valid cron Bearer token in cron mode.
src/app/api/cron/lotw-upload/route.ts Removes trusted-host sniffing; enforces CRON_SECRET presence and Bearer validation; forwards Authorization internally.
src/app/api/cron/lotw-download/route.ts Removes trusted-host sniffing; enforces CRON_SECRET presence and Bearer validation; forwards Authorization internally.
README.md Documents CRON_SECRET requirements and example scheduler invocations for the cron endpoints.

@patrickrb
patrickrb merged commit e4aa9e2 into main Jul 13, 2026
8 checks passed
@patrickrb
patrickrb deleted the fix/cron-auth-hardening branch July 13, 2026 17:40
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.

2 participants