This issue is raised as part of GSSoC'26. Kindly consider assigning it to me.
Summary
In src/app/api/streak/freeze/route.ts, the POST handler only checks
for a duplicate freeze on today's date specifically:
.eq("freeze_date", today)
There is no check for how many total pending freezes a user already
holds. A user can call POST /api/streak/freeze with future dates
repeatedly and stockpile an unlimited number of unused freezes,
completely bypassing the intended one-freeze limit.
Steps to Reproduce
- Call POST /api/streak/freeze for today
- Modify the request to use tomorrow's date
- Repeat for future dates
- Observe unlimited freezes accumulate with no restriction
Expected Behavior
Users should be limited to a maximum number of unused freezes
at any time (e.g. 1 or a configurable max).
Actual Behavior
No upper limit exists. Users can stockpile unlimited pending
freezes by targeting future dates.
Fix
Add a count check before allowing new freeze creation:
const { count } = await supabaseAdmin
.from("streak_freezes")
.select("*", { count: "exact", head: true })
.eq("user_id", user.id)
.gte("freeze_date", today);
const MAX_PENDING_FREEZES = 1;
if (count && count >= MAX_PENDING_FREEZES) {
return Response.json(
{ error: "You already have a pending freeze." },
{ status: 409 }
);
}
This issue is raised as part of GSSoC'26. Kindly consider assigning it to me.
Summary
In
src/app/api/streak/freeze/route.ts, the POST handler only checksfor a duplicate freeze on today's date specifically:
.eq("freeze_date", today)
There is no check for how many total pending freezes a user already
holds. A user can call POST /api/streak/freeze with future dates
repeatedly and stockpile an unlimited number of unused freezes,
completely bypassing the intended one-freeze limit.
Steps to Reproduce
Expected Behavior
Users should be limited to a maximum number of unused freezes
at any time (e.g. 1 or a configurable max).
Actual Behavior
No upper limit exists. Users can stockpile unlimited pending
freezes by targeting future dates.
Fix
Add a count check before allowing new freeze creation:
const { count } = await supabaseAdmin
.from("streak_freezes")
.select("*", { count: "exact", head: true })
.eq("user_id", user.id)
.gte("freeze_date", today);
const MAX_PENDING_FREEZES = 1;
if (count && count >= MAX_PENDING_FREEZES) {
return Response.json(
{ error: "You already have a pending freeze." },
{ status: 409 }
);
}