Skip to content

Commit cb0beb3

Browse files
committed
fix(api): make body-size caps NaN-safe and raise chat input/attachment limits
- DEFAULT_MAX_JSON_BODY_BYTES and CHAT_MAX_REQUEST_BYTES now fall back to hardcoded defaults (50 MB / 220 MB) when the env value is missing or non-numeric, so a misconfig can't silently produce a NaN cap that never rejects. - Raise CHAT_MAX_REQUEST_BYTES default to 220 MB to cover 15 base64 file attachments, and MAX_CHAT_INPUT_CHARS to 1,000,000. - Minor: tidy use-inline-rename onSave type; drop two redundant test comments.
1 parent cbfe114 commit cb0beb3

7 files changed

Lines changed: 8 additions & 7 deletions

File tree

apps/sim/app/api/chat/[identifier]/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ function toChatConfigResponse(deployment: ChatConfigSource) {
4242
export const dynamic = 'force-dynamic'
4343
export const runtime = 'nodejs'
4444

45-
const CHAT_MAX_REQUEST_BYTES = Number.parseInt(env.CHAT_MAX_REQUEST_BYTES, 10)
45+
const CHAT_MAX_REQUEST_BYTES = Number.parseInt(env.CHAT_MAX_REQUEST_BYTES, 10) || 220 * 1024 * 1024
4646

4747
export const POST = withRouteHandler(
4848
async (request: NextRequest, context: { params: Promise<{ identifier: string }> }) => {

apps/sim/app/api/files/authorization.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ describe('public-context access (profile-pictures / og-images / workspace-logos)
177177
})
178178

179179
it('denies a cross-tenant delete that names a workspace key under a public context', async () => {
180-
// Reported attack: a workspace key passed under a public context to dodge the ownership check.
181180
await expect(write('workspace/victim-ws/123-report.pdf', 'og-images')).resolves.toBe(false)
182181
expect(mockGetUserEntityPermissions).not.toHaveBeenCalled()
183182
})

apps/sim/app/api/files/delete/route.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@ describe('File Delete API Route', () => {
200200
})
201201

202202
it('rejects a client context that disagrees with the key prefix', async () => {
203-
// Reported attack: a workspace key passed under a public context to dodge the ownership check.
204203
const req = createMockRequest('POST', {
205204
filePath: '/api/files/serve/s3/workspace/victim-ws/1234-report.pdf',
206205
context: 'og-images',

apps/sim/hooks/use-inline-rename.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ interface UseInlineRenameProps {
99
* `mutateAsync(...)`) — NOT a fire-and-forget `mutate(...)` — so `isSaving`
1010
* spans the in-flight request and a rejection can revive the edit session.
1111
*/
12-
onSave: (id: string, newName: string) => void | Promise<unknown>
12+
onSave: (id: string, newName: string) => undefined | Promise<unknown>
1313
}
1414

1515
/**

apps/sim/lib/api/contracts/chats.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export const deployedChatAuthBodySchema = z.object({
110110
})
111111
export type DeployedChatAuthBody = z.input<typeof deployedChatAuthBodySchema>
112112

113-
const MAX_CHAT_INPUT_CHARS = 100_000
113+
const MAX_CHAT_INPUT_CHARS = 1_000_000
114114
const MAX_CHAT_FILE_DATA_CHARS = 14 * 1024 * 1024
115115
const MAX_CHAT_FILES = 15
116116

apps/sim/lib/api/server/validation.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ import {
2020
* and parse into memory. Next.js App Router imposes no body cap, so without
2121
* this an unauthenticated caller could buffer an arbitrarily large body before
2222
* schema validation runs. Override per-route via `ParseRequestOptions.maxBodyBytes`.
23+
* Falls back to 50 MB if the env value is missing or non-numeric so a misconfig
24+
* can never silently disable the cap (a NaN limit would never reject).
2325
*/
24-
export const DEFAULT_MAX_JSON_BODY_BYTES = Number.parseInt(env.API_MAX_JSON_BODY_BYTES, 10)
26+
export const DEFAULT_MAX_JSON_BODY_BYTES =
27+
Number.parseInt(env.API_MAX_JSON_BODY_BYTES, 10) || 50 * 1024 * 1024
2528

2629
export interface ValidationErrorBody {
2730
error: string

apps/sim/lib/core/config/env.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ export const env = createEnv({
244244
// Admission & Burst Protection
245245
ADMISSION_GATE_MAX_INFLIGHT: z.string().optional().default('500'), // Max concurrent in-flight execution requests per pod
246246
API_MAX_JSON_BODY_BYTES: z.string().optional().default('52428800'),// Default max JSON request body size for contract routes (50 MB)
247-
CHAT_MAX_REQUEST_BYTES: z.string().optional().default('20971520'),// Max request body size for the public deployed-chat endpoint (20 MB)
247+
CHAT_MAX_REQUEST_BYTES: z.string().optional().default('230686720'),// Max request body size for the public deployed-chat endpoint (220 MB; covers 15 base64 file attachments)
248248

249249
// Rate Limiting Configuration
250250
RATE_LIMIT_WINDOW_MS: z.string().optional().default('60000'), // Rate limit window duration in milliseconds (default: 1 minute)

0 commit comments

Comments
 (0)