fix(mcp): correct fetchFn fallback order in mcpAuthGuarded (#5423)

Spread order previously let an explicit fetchFn (including fetchFn: undefined)
in options silently disable the SSRF-guarded default. Fallback is now applied
after the spread so the guard always wins unless a real override is passed.

fix(tools): handle non-numeric Drive file size in early size check

Guard the pre-download size check against a malformed metadata.size string
so it's skipped explicitly instead of relying on an incidental NaN no-op;
the streaming cap on the actual download still enforces the limit either way.
This commit is contained in:
Waleed
2026-07-04 16:44:46 -07:00
committed by GitHub
parent f456ed9a0b
commit 3edaae31fe
4 changed files with 42 additions and 6 deletions
@@ -133,6 +133,30 @@ describe('POST /api/tools/google_drive/download', () => {
expect(data.success).toBe(false)
})
it('proceeds to the streamed download when metadata size is malformed', async () => {
mockSecureFetchWithPinnedIP
.mockResolvedValueOnce(
jsonResponse({
id: 'file-abc',
name: 'report.pdf',
mimeType: 'application/pdf',
size: 'not-a-number',
capabilities: { canReadRevisions: false },
})
)
.mockResolvedValueOnce(fileResponse(1024))
const response = await POST(createMockRequest('POST', baseBody))
expect(response.status).toBe(200)
const data = (await response.json()) as { success: boolean; output: { file: { size: number } } }
expect(data.success).toBe(true)
expect(data.output.file.size).toBe(1024)
// The early size check should be skipped, but the streaming cap must still apply.
const downloadCall = mockSecureFetchWithPinnedIP.mock.calls[1]
expect(downloadCall[2]).toMatchObject({ maxResponseBytes: MAX_FILE_SIZE })
})
it('does not require a metadata size for Google Workspace exports', async () => {
mockSecureFetchWithPinnedIP
.mockResolvedValueOnce(
@@ -188,11 +188,10 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
logger.info(`[${requestId}] Downloading regular file`, { fileId, mimeType: fileMimeType })
if (metadata.size) {
assertKnownSizeWithinLimit(
Number.parseInt(metadata.size, 10),
MAX_FILE_SIZE,
`Google Drive file ${fileId}`
)
const parsedSize = Number.parseInt(metadata.size, 10)
if (Number.isFinite(parsedSize)) {
assertKnownSizeWithinLimit(parsedSize, MAX_FILE_SIZE, `Google Drive file ${fileId}`)
}
}
const downloadUrl = `https://www.googleapis.com/drive/v3/files/${fileId}?alt=media&supportsAllDrives=true`
+13
View File
@@ -51,4 +51,17 @@ describe('mcpAuthGuarded', () => {
fetchFn: overrideFetch,
})
})
it('falls back to the SSRF-guarded fetch when fetchFn is explicitly undefined', async () => {
await mcpAuthGuarded(provider, {
serverUrl: 'https://mcp.example.com/mcp',
fetchFn: undefined,
})
expect(mockCreateSsrfGuardedMcpFetch).toHaveBeenCalledTimes(1)
expect(mockAuth).toHaveBeenCalledWith(provider, {
serverUrl: 'https://mcp.example.com/mcp',
fetchFn: mockGuardedFetch,
})
})
})
+1 -1
View File
@@ -15,5 +15,5 @@ export function mcpAuthGuarded(
provider: OAuthClientProvider,
options: McpAuthOptions
): ReturnType<typeof auth> {
return auth(provider, { fetchFn: createSsrfGuardedMcpFetch(), ...options })
return auth(provider, { ...options, fetchFn: options.fetchFn ?? createSsrfGuardedMcpFetch() })
}