From c2041afe9cddc70865900a005d0599e49c4a7bef Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 5 Mar 2026 19:18:07 -0800 Subject: [PATCH] fix(selectors): add missing context fields to resolution, ensureCredential to sharepoint.lists, and siteId validation - Add baseId, datasetId, serviceDeskId to SelectorResolutionArgs, ExtendedSelectorContext, extractExtendedContext, useSelectorDisplayName, and resolveSelectorForSubBlock so cascading selectors resolve correctly through the resolution path. - Add ensureCredential guard to sharepoint.lists registry entry. - Add regex validation for SharePoint siteId format (hostname,GUID,GUID). --- apps/sim/app/api/tools/sharepoint/lists/route.ts | 5 +++++ apps/sim/hooks/selectors/registry.ts | 6 ++++-- apps/sim/hooks/selectors/resolution.ts | 6 ++++++ apps/sim/hooks/use-selector-display-name.ts | 12 ++++++++++++ apps/sim/lib/workflows/comparison/resolve-values.ts | 12 ++++++++++++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/api/tools/sharepoint/lists/route.ts b/apps/sim/app/api/tools/sharepoint/lists/route.ts index 68399c72cd..32ca9eb489 100644 --- a/apps/sim/app/api/tools/sharepoint/lists/route.ts +++ b/apps/sim/app/api/tools/sharepoint/lists/route.ts @@ -46,6 +46,11 @@ export async function GET(request: NextRequest) { return NextResponse.json({ error: 'Site ID is required' }, { status: 400 }) } + const SITE_ID_RE = /^[\w.\-,]+$/ + if (siteId.length > 512 || !SITE_ID_RE.test(siteId)) { + return NextResponse.json({ error: 'Invalid site ID format' }, { status: 400 }) + } + const credentialIdValidation = validateAlphanumericId(credentialId, 'credentialId', 255) if (!credentialIdValidation.isValid) { logger.warn(`[${requestId}] Invalid credential ID`, { error: credentialIdValidation.error }) diff --git a/apps/sim/hooks/selectors/registry.ts b/apps/sim/hooks/selectors/registry.ts index a15d1674d8..9b997aa978 100644 --- a/apps/sim/hooks/selectors/registry.ts +++ b/apps/sim/hooks/selectors/registry.ts @@ -721,10 +721,11 @@ const registry: Record = { ], enabled: ({ context }) => Boolean(context.credentialId && context.siteId), fetchList: async ({ context }: SelectorQueryArgs) => { + const credentialId = ensureCredential(context, 'sharepoint.lists') if (!context.siteId) throw new Error('Missing site ID for sharepoint.lists selector') const data = await fetchJson<{ lists: SharepointList[] }>('/api/tools/sharepoint/lists', { searchParams: { - credentialId: context.credentialId, + credentialId, siteId: context.siteId, }, }) @@ -732,9 +733,10 @@ const registry: Record = { }, fetchById: async ({ context, detailId }: SelectorQueryArgs) => { if (!detailId || !context.siteId) return null + const credentialId = ensureCredential(context, 'sharepoint.lists') const data = await fetchJson<{ lists: SharepointList[] }>('/api/tools/sharepoint/lists', { searchParams: { - credentialId: context.credentialId, + credentialId, siteId: context.siteId, }, }) diff --git a/apps/sim/hooks/selectors/resolution.ts b/apps/sim/hooks/selectors/resolution.ts index 9f299d99d8..b37b176132 100644 --- a/apps/sim/hooks/selectors/resolution.ts +++ b/apps/sim/hooks/selectors/resolution.ts @@ -18,6 +18,9 @@ export interface SelectorResolutionArgs { siteId?: string collectionId?: string spreadsheetId?: string + baseId?: string + datasetId?: string + serviceDeskId?: string } export function resolveSelectorForSubBlock( @@ -38,6 +41,9 @@ export function resolveSelectorForSubBlock( siteId: args.siteId, collectionId: args.collectionId, spreadsheetId: args.spreadsheetId, + baseId: args.baseId, + datasetId: args.datasetId, + serviceDeskId: args.serviceDeskId, mimeType: subBlock.mimeType, }, allowSearch: subBlock.selectorAllowSearch ?? true, diff --git a/apps/sim/hooks/use-selector-display-name.ts b/apps/sim/hooks/use-selector-display-name.ts index 91d6f7f817..7ead246266 100644 --- a/apps/sim/hooks/use-selector-display-name.ts +++ b/apps/sim/hooks/use-selector-display-name.ts @@ -18,6 +18,9 @@ interface SelectorDisplayNameArgs { planId?: string teamId?: string knowledgeBaseId?: string + baseId?: string + datasetId?: string + serviceDeskId?: string } export function useSelectorDisplayName({ @@ -30,6 +33,9 @@ export function useSelectorDisplayName({ planId, teamId, knowledgeBaseId, + baseId, + datasetId, + serviceDeskId, }: SelectorDisplayNameArgs) { const detailId = typeof value === 'string' && value.length > 0 ? value : undefined @@ -43,6 +49,9 @@ export function useSelectorDisplayName({ planId, teamId, knowledgeBaseId, + baseId, + datasetId, + serviceDeskId, }) }, [ subBlock, @@ -54,6 +63,9 @@ export function useSelectorDisplayName({ planId, teamId, knowledgeBaseId, + baseId, + datasetId, + serviceDeskId, ]) const key = resolution?.key diff --git a/apps/sim/lib/workflows/comparison/resolve-values.ts b/apps/sim/lib/workflows/comparison/resolve-values.ts index 4912654023..9a041e7cc9 100644 --- a/apps/sim/lib/workflows/comparison/resolve-values.ts +++ b/apps/sim/lib/workflows/comparison/resolve-values.ts @@ -52,6 +52,9 @@ interface ExtendedSelectorContext { siteId?: string collectionId?: string spreadsheetId?: string + baseId?: string + datasetId?: string + serviceDeskId?: string } function getSemanticFallback(subBlockId: string, subBlockConfig?: SubBlockConfig): string { @@ -163,6 +166,9 @@ async function resolveSelectorValue( siteId: extendedContext.siteId, collectionId: extendedContext.collectionId, spreadsheetId: extendedContext.spreadsheetId, + baseId: extendedContext.baseId, + datasetId: extendedContext.datasetId, + serviceDeskId: extendedContext.serviceDeskId, } if (definition.fetchById) { @@ -240,6 +246,9 @@ function extractExtendedContext( siteId: getStringValue('siteId'), collectionId: getStringValue('collectionId'), spreadsheetId: getStringValue('spreadsheetId') || getStringValue('fileId'), + baseId: getStringValue('baseId') || getStringValue('baseSelector'), + datasetId: getStringValue('datasetId') || getStringValue('datasetSelector'), + serviceDeskId: getStringValue('serviceDeskId') || getStringValue('serviceDeskSelector'), } } @@ -313,6 +322,9 @@ export async function resolveValueForDisplay( siteId: extendedContext.siteId, collectionId: extendedContext.collectionId, spreadsheetId: extendedContext.spreadsheetId, + baseId: extendedContext.baseId, + datasetId: extendedContext.datasetId, + serviceDeskId: extendedContext.serviceDeskId, }) if (resolution?.key) {