fix: close SSRF/rebinding, IDOR, and stale-session authz gaps found in audit
Bump to 0.5.1. Fixes: unfollowed-redirect SSRF + DNS-rebinding in AI url-import and webhook dispatch (new safeFetch with IP-pinned undici dispatcher); cross-user photo deletion via unvalidated recipe/review storage keys; comment-moderation and tier-quota checks trusting a stale cached session role/tier instead of the DB. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+10
-2
@@ -1,5 +1,5 @@
|
||||
import { db } from "@epicure/db";
|
||||
import { tierDefinitions, userUsage } from "@epicure/db";
|
||||
import { tierDefinitions, userUsage, users } from "@epicure/db";
|
||||
import { eq, sql } from "@epicure/db";
|
||||
|
||||
function currentMonth() {
|
||||
@@ -24,16 +24,24 @@ export class TierLimitError extends Error {
|
||||
* single SQL statement, eliminating the TOCTOU race that existed when
|
||||
* checkTierLimit and incrementUsage were called separately.
|
||||
*
|
||||
* The caller's `userTier` is never trusted directly — it comes from the
|
||||
* session's 5-minute cookieCache (see lib/auth/server.ts), so a just-downgraded
|
||||
* user would otherwise keep the old tier's caps for up to 5 minutes. The
|
||||
* current tier is always re-read from the DB here.
|
||||
*
|
||||
* Throws TierLimitError if the limit has already been reached.
|
||||
* Use this instead of the separate checkTierLimit + incrementUsage pair
|
||||
* for "recipe" and "aiCall" keys.
|
||||
*/
|
||||
export async function checkAndIncrementTierLimit(
|
||||
userId: string,
|
||||
userTier: "free" | "pro",
|
||||
fallbackTier: "free" | "pro",
|
||||
key: "recipe" | "aiCall" | "storage",
|
||||
amount = 1
|
||||
): Promise<void> {
|
||||
const [dbUser] = await db.select({ tier: users.tier }).from(users).where(eq(users.id, userId));
|
||||
const userTier = (dbUser?.tier as "free" | "pro" | undefined) ?? fallbackTier;
|
||||
|
||||
const [tierDef] = await db
|
||||
.select()
|
||||
.from(tierDefinitions)
|
||||
|
||||
Reference in New Issue
Block a user