Skip to content

Commit de8c070

Browse files
committed
fix(connectors): validate Gmail's thread cap with the sync parser and reject invalid Date metadata
1 parent f7a44a1 commit de8c070

4 files changed

Lines changed: 25 additions & 5 deletions

File tree

apps/sim/connectors/gmail/gmail.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,14 @@ describe('gmail listDocuments with a blank maxThreads', () => {
104104
expect(mockFetchWithRetry).not.toHaveBeenCalled()
105105
})
106106
})
107+
108+
describe('gmail validateConfig maxThreads', () => {
109+
it('refuses what the sync parser would refuse, before any request', async () => {
110+
for (const maxThreads of ['1.5', 'abc', '-1']) {
111+
const result = await gmailConnector.validateConfig('token', { maxThreads })
112+
expect(result.valid).toBe(false)
113+
expect(result.error).toBe('Max threads must be a non-negative whole number')
114+
}
115+
expect(mockFetchWithRetry).not.toHaveBeenCalled()
116+
})
117+
})

apps/sim/connectors/gmail/gmail.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -565,10 +565,15 @@ export const gmailConnector: ConnectorConfig = {
565565
accessToken: string,
566566
sourceConfig: Record<string, unknown>
567567
): Promise<{ valid: boolean; error?: string }> => {
568-
const maxThreads = sourceConfig.maxThreads as string | undefined
569-
570-
if (maxThreads && (Number.isNaN(Number(maxThreads)) || Number(maxThreads) <= 0)) {
571-
return { valid: false, error: 'Max threads must be a positive number' }
568+
/** The same parser the sync uses, so a value that saves is a value that syncs. */
569+
try {
570+
parseDefaultedUnlimitedSafeInteger(
571+
sourceConfig.maxThreads,
572+
DEFAULT_MAX_THREADS,
573+
'Max threads must be a non-negative whole number'
574+
)
575+
} catch (error) {
576+
return { valid: false, error: getErrorMessage(error) }
572577
}
573578

574579
try {

apps/sim/lib/knowledge/connectors/source-modified-at.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ describe('resolveSourceModifiedAt', () => {
4646
).toBe('2026-08-01T00:00:00.000Z')
4747
})
4848

49+
it('rejects an invalid Date instance', () => {
50+
expect(resolveSourceModifiedAt({ modifiedTime: new Date('not a date') })).toBeNull()
51+
})
52+
4953
it('rejects placeholders and far-future values', () => {
5054
expect(resolveSourceModifiedAt({ modifiedTime: 0 }, NOW)).toBeNull()
5155
expect(resolveSourceModifiedAt({ modifiedTime: '1970-01-01T00:00:00Z' }, NOW)).toBeNull()

apps/sim/lib/knowledge/connectors/source-modified-at.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const EARLIEST_PLAUSIBLE_MS = Date.UTC(1990, 0, 1)
2424
const FUTURE_TOLERANCE_MS = 24 * 60 * 60 * 1000
2525

2626
function toDate(value: unknown): Date | null {
27-
if (value instanceof Date) return value
27+
if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value
2828
if (typeof value === 'number' && Number.isFinite(value)) {
2929
/** Seconds-since-epoch values are far too small to be milliseconds after 1990. */
3030
return new Date(value < 1e11 ? value * 1000 : value)

0 commit comments

Comments
 (0)