From 7b238d79c3fe48c5b075f2f622ed74e4c45c1294 Mon Sep 17 00:00:00 2001 From: mrinal Date: Fri, 2 Oct 2026 01:08:18 +0000 Subject: [PATCH] fix(ui): reject unsafe rate limit integers Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../users/_components/userRateLimitPayload.test.ts | 10 +++++++--- .../users/_components/userRateLimitPayload.ts | 2 +- .../users/_components/user_edit_view.test.tsx | 4 ++-- .../(dashboard)/users/_components/user_edit_view.tsx | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/userRateLimitPayload.test.ts b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/userRateLimitPayload.test.ts index c64f6e6a88a..c7ed31f1df6 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/userRateLimitPayload.test.ts +++ b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/userRateLimitPayload.test.ts @@ -37,11 +37,15 @@ describe("isValidRateLimitInput", () => { ["number zero", 0], ["integer string", "12"], ["integer", 12], + ["maximum safe integer", String(Number.MAX_SAFE_INTEGER)], ])("accepts %s", (_label, value) => { expect(isValidRateLimitInput(value)).toBe(true); }); - it.each(["1.5", "-1", "abc", "1e400"])("rejects %s", (value) => { - expect(isValidRateLimitInput(value)).toBe(false); - }); + it.each(["1.5", "-1", "abc", "1e400", "9007199254740992", "9007199254740993", "1e30", "9999999999999999999"])( + "rejects %s", + (value) => { + expect(isValidRateLimitInput(value)).toBe(false); + }, + ); }); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/userRateLimitPayload.ts b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/userRateLimitPayload.ts index 82c0fb3bf88..90ff9dd58ed 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/userRateLimitPayload.ts +++ b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/userRateLimitPayload.ts @@ -13,5 +13,5 @@ export const isValidRateLimitInput = (value: string | number | null | undefined) return true; } const number = Number(value); - return Number.isFinite(number) && Number.isInteger(number) && number >= 0; + return Number.isSafeInteger(number) && number >= 0; }; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/user_edit_view.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/user_edit_view.test.tsx index 4a3c165b015..fe69257e21c 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/user_edit_view.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/user_edit_view.test.tsx @@ -520,7 +520,7 @@ describe("UserEditView", () => { expect(typeof onSubmit.mock.calls[0][0].rpm_limit).toBe("number"); }); - it.each(["-1", "1.5"])("rejects an invalid TPM limit of %s", async (value) => { + it.each(["-1", "1.5", "1e30", "9007199254740992"])("rejects an invalid TPM limit of %s", async (value) => { const onSubmit = vi.fn(); renderWithProviders(); @@ -535,7 +535,7 @@ describe("UserEditView", () => { fireEvent.submit(form); expect( - await screen.findByText("Enter a non-negative whole number, or leave empty for unlimited"), + await screen.findByText("Enter a whole number from 0 to 9007199254740991, or leave empty for unlimited"), ).toBeInTheDocument(); expect(onSubmit).not.toHaveBeenCalled(); }); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/user_edit_view.tsx b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/user_edit_view.tsx index f30ba1ccb5f..75d35ebe561 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/user_edit_view.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/user_edit_view.tsx @@ -71,11 +71,11 @@ const budgetSchema = (unlimitedBudget: boolean) => tpm_limit: z .union([z.string(), z.number()]) .nullish() - .refine(isValidRateLimitInput, "Enter a non-negative whole number, or leave empty for unlimited"), + .refine(isValidRateLimitInput, "Enter a whole number from 0 to 9007199254740991, or leave empty for unlimited"), rpm_limit: z .union([z.string(), z.number()]) .nullish() - .refine(isValidRateLimitInput, "Enter a non-negative whole number, or leave empty for unlimited"), + .refine(isValidRateLimitInput, "Enter a whole number from 0 to 9007199254740991, or leave empty for unlimited"), }); type UserEditFormValues = z.infer>;