Get this on every PR automatically. Webhook fires, AI reviews, you approve.
Install on vercel/eve →
// reviewed by pulllight

PullLight found 2 issues

vercel/eve #710 — feat(eve): external cron mode for self-hosted builds (EVE_EX… by @warmwind Jul 12, 2026
1 high 1 medium
🔍
// convert to your repo
PullLight caught 2 1 high, 1 medium on this PR.
Install on vercel/eve to get this on every PR automatically — 60 seconds.
Findings
2 issues
high auth
`timingSafeEqualStrings` short-circuits with `false` when the lengths differ, but this early-exit leaks the length of the expected secret via a timing side-channel. An attacker can binary-search the secret length by observing whether the function returns immediately (lengths differ) or takes the full `timingSafeEqual` time. Fix by always running `timingSafeEqual` on equal-length buffers — pad or hash both sides to a fixed length before comparing.
// packages/eve/src/internal/nitro/routes/external-cron.ts:66
⚡ Suggested fix
function timingSafeEqualStrings(left: string, right: string): boolean {
  const leftBuffer = Buffer.from(left);
  const rightBuffer = Buffer.from(right);
  // Pad to the same length so timingSafeEqual always runs, preventing
  // length-based timing leaks. We still return false when lengths differ.
  const maxLen = Math.max(leftBuffer.length, rightBuffer.length);
  const paddedLeft = Buffer.concat([leftBuffer, Buffer.alloc(maxLen - leftBuffer.length)]);
  const paddedRight = Buffer.concat([rightBuffer, Buffer.alloc(maxLen - rightBuffer.length)]);
  return leftBuffer.length === rightBuffer.length && timingSafeEqual(paddedLeft, paddedRight);
}
medium error-handling
`Promise.all` over `dispatchScheduleTask` calls means a single failing dispatch rejects the entire promise, causing the handler to throw an unhandled error (no try/catch) and return a 500 with no body. A partial failure (one schedule errors, others succeed) silently drops all results. Consider `Promise.allSettled` and returning per-schedule success/error status.
// packages/eve/src/internal/nitro/routes/external-cron.ts:55
model: claude-sonnet-4-5   input: 11028 tokens   output: 621 tokens