fix: harden auth middleware security #1

Merged
schwifty merged 1 commit from schwifty/fix-auth-security into main 2026-03-23 01:44:02 +00:00
Collaborator

Changes

  1. Exact route matching — replaced str_contains() with === in PUBLIC_ROUTES check to prevent substring bypass attacks
  2. Removed /api/admin/ bypass — the blanket str_contains($path, "/api/admin/") was making ALL admin endpoints publicly accessible without auth
  3. Added X-Cron-Secret header check — cron endpoints now require PAYFRIT_CRON_SECRET env var to be set on the server, and callers must pass matching X-Cron-Secret header. Uses hash_equals() for timing-safe comparison.

Deployment Notes

⚠️ Before deploying, Raj needs to:

  • Set PAYFRIT_CRON_SECRET env var on dev and biz servers (any strong random string)
  • Update cron jobs to pass -H "X-Cron-Secret: <the-secret>" in their curl calls

Without this, cron endpoints will return 403 until configured.

Files Changed

  • api/helpers.php — route matching fix + new requireCronSecret() function
  • cron/expireStaleChats.php — added cron secret check
  • cron/expireTabs.php — added cron secret check
  • api/admin/scheduledTasks/runDue.php — added cron secret check
## Changes 1. **Exact route matching** — replaced `str_contains()` with `===` in PUBLIC_ROUTES check to prevent substring bypass attacks 2. **Removed /api/admin/ bypass** — the blanket `str_contains($path, "/api/admin/")` was making ALL admin endpoints publicly accessible without auth 3. **Added X-Cron-Secret header check** — cron endpoints now require `PAYFRIT_CRON_SECRET` env var to be set on the server, and callers must pass matching `X-Cron-Secret` header. Uses `hash_equals()` for timing-safe comparison. ## Deployment Notes ⚠️ **Before deploying**, Raj needs to: - Set `PAYFRIT_CRON_SECRET` env var on dev and biz servers (any strong random string) - Update cron jobs to pass `-H "X-Cron-Secret: <the-secret>"` in their curl calls Without this, cron endpoints will return 403 until configured. ## Files Changed - `api/helpers.php` — route matching fix + new `requireCronSecret()` function - `cron/expireStaleChats.php` — added cron secret check - `cron/expireTabs.php` — added cron secret check - `api/admin/scheduledTasks/runDue.php` — added cron secret check
schwifty added 1 commit 2026-03-23 01:43:58 +00:00
1. Switch str_contains() to exact match ($path === $route) in PUBLIC_ROUTES check
   to prevent substring-based route bypass attacks.

2. Remove blanket /api/admin/ bypass that was letting all admin endpoints through
   without authentication.

3. Add requireCronSecret() — cron/scheduled task endpoints now require a valid
   X-Cron-Secret header matching the PAYFRIT_CRON_SECRET env var. Uses
   hash_equals() for timing-safe comparison. Applied to:
   - cron/expireStaleChats.php
   - cron/expireTabs.php
   - api/admin/scheduledTasks/runDue.php
schwifty merged commit cc7d6f6b4f into main 2026-03-23 01:44:02 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: payfrit/payfrit-api#1
No description provided.