Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
9669ca4
feat(microsoft-excel): add SharePoint drive support for Excel integra…
waleedlatif1 Apr 14, 2026
6162253
fix(microsoft-excel): address PR review comments
waleedlatif1 Apr 14, 2026
a3c93ee
fix(microsoft-excel): validate driveId in files route
waleedlatif1 Apr 14, 2026
780fa90
fix(microsoft-excel): unblock OneDrive users and validate driveId in …
waleedlatif1 Apr 14, 2026
f18af3c
fix(microsoft-excel): validate driveId in getItemBasePath utility
waleedlatif1 Apr 14, 2026
65308e4
fix(microsoft-excel): use centralized input validation
waleedlatif1 Apr 14, 2026
2884587
lint
waleedlatif1 Apr 14, 2026
649c3e6
improvement(microsoft-excel): add File Source dropdown to control Sha…
waleedlatif1 Apr 14, 2026
8b1c88c
fix(microsoft-excel): fix canonical param test failures
waleedlatif1 Apr 15, 2026
326114d
fix(microsoft-excel): address PR review feedback for SharePoint drive…
waleedlatif1 Apr 15, 2026
3be18ca
fix(microsoft-excel): use validateMicrosoftGraphId for driveId valida…
waleedlatif1 Apr 15, 2026
12231db
fix(microsoft-excel): use validatePathSegment with strict pattern for…
waleedlatif1 Apr 15, 2026
8148260
lint
waleedlatif1 Apr 15, 2026
16ad6ce
fix(microsoft-excel): reorder driveId before spreadsheetId in v1 block
waleedlatif1 Apr 15, 2026
d1b8778
fix(microsoft-excel): clear manualDriveId when fileSource changes
waleedlatif1 Apr 15, 2026
def6e90
refactor(microsoft-excel): use getItemBasePath in sheets route to rem…
waleedlatif1 Apr 15, 2026
5334c2b
lint
waleedlatif1 Apr 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(microsoft-excel): address PR review feedback for SharePoint drive…
… support

- Clear stale driveId/siteId/spreadsheetId when fileSource changes by adding
  fileSource to dependsOn arrays for siteSelector, driveSelector, and
  spreadsheetId selectors
- Reorder manualDriveId before manualSpreadsheetId in advanced mode for
  logical top-down flow
- Validate spreadsheetId with validateMicrosoftGraphId in getItemBasePath()
  and sheets route to close injection vector (uses permissive validator that
  accepts ! chars in OneDrive item IDs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • Loading branch information
waleedlatif1 and claude committed Apr 15, 2026
commit 326114d1ea9931853319853933dffbbee58bd37b
10 changes: 9 additions & 1 deletion apps/sim/app/api/tools/microsoft_excel/sheets/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server'
import { authorizeCredentialUse } from '@/lib/auth/credential-access'
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import {
validateAlphanumericId,
validateMicrosoftGraphId,
} from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request'
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'

Expand Down Expand Up @@ -63,6 +66,11 @@ export async function GET(request: NextRequest) {
`[${requestId}] Fetching worksheets from Microsoft Graph API for workbook ${spreadsheetId}`
)

const spreadsheetValidation = validateMicrosoftGraphId(spreadsheetId, 'spreadsheetId')
if (!spreadsheetValidation.isValid) {
return NextResponse.json({ error: spreadsheetValidation.error }, { status: 400 })
}

if (driveId) {
const driveIdValidation = validateAlphanumericId(driveId, 'driveId')
if (!driveIdValidation.isValid) {
Expand Down
26 changes: 13 additions & 13 deletions apps/sim/blocks/blocks/microsoft_excel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ export const MicrosoftExcelV2Block: BlockConfig<MicrosoftExcelV2Response> = {
selectorKey: 'sharepoint.sites',
requiredScopes: [],
placeholder: 'Select a SharePoint site',
dependsOn: ['credential'],
dependsOn: ['credential', 'fileSource'],
condition: { field: 'fileSource', value: 'sharepoint' },
required: { field: 'fileSource', value: 'sharepoint' },
mode: 'basic',
Expand All @@ -430,7 +430,7 @@ export const MicrosoftExcelV2Block: BlockConfig<MicrosoftExcelV2Response> = {
selectorKey: 'microsoft.excel.drives',
selectorAllowSearch: false,
placeholder: 'Select a document library',
dependsOn: ['credential', 'siteSelector'],
dependsOn: ['credential', 'siteSelector', 'fileSource'],
condition: { field: 'fileSource', value: 'sharepoint' },
required: { field: 'fileSource', value: 'sharepoint' },
mode: 'basic',
Expand All @@ -446,19 +446,9 @@ export const MicrosoftExcelV2Block: BlockConfig<MicrosoftExcelV2Response> = {
requiredScopes: [],
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
placeholder: 'Select a spreadsheet',
dependsOn: { all: ['credential'], any: ['credential', 'driveSelector'] },
dependsOn: { all: ['credential', 'fileSource'], any: ['credential', 'driveSelector'] },
mode: 'basic',
},
// Manual Spreadsheet ID (advanced mode)
{
id: 'manualSpreadsheetId',
title: 'Spreadsheet ID',
type: 'short-input',
canonicalParamId: 'spreadsheetId',
placeholder: 'Enter spreadsheet ID',
dependsOn: { all: ['credential'], any: ['credential', 'manualDriveId'] },
mode: 'advanced',
},
// Drive ID for SharePoint (advanced mode, only when SharePoint is selected)
{
id: 'manualDriveId',
Expand All @@ -469,6 +459,16 @@ export const MicrosoftExcelV2Block: BlockConfig<MicrosoftExcelV2Response> = {
condition: { field: 'fileSource', value: 'sharepoint' },
Comment thread
waleedlatif1 marked this conversation as resolved.
mode: 'advanced',
},
Comment thread
waleedlatif1 marked this conversation as resolved.
// Manual Spreadsheet ID (advanced mode)
{
id: 'manualSpreadsheetId',
title: 'Spreadsheet ID',
type: 'short-input',
canonicalParamId: 'spreadsheetId',
placeholder: 'Enter spreadsheet ID',
dependsOn: { all: ['credential'], any: ['credential', 'manualDriveId'] },
Comment thread
waleedlatif1 marked this conversation as resolved.
mode: 'advanced',
},
// Sheet Name Selector (basic mode)
{
id: 'sheetName',
Expand Down
16 changes: 12 additions & 4 deletions apps/sim/tools/microsoft_excel/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { createLogger } from '@sim/logger'
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import {
validateAlphanumericId,
validateMicrosoftGraphId,
} from '@/lib/core/security/input-validation'
import type { ExcelCellValue } from '@/tools/microsoft_excel/types'

const logger = createLogger('MicrosoftExcelUtils')
Expand All @@ -10,10 +13,15 @@ const logger = createLogger('MicrosoftExcelUtils')
* When driveId is omitted, uses /me/drive/items/{itemId} (personal OneDrive).
*/
export function getItemBasePath(spreadsheetId: string, driveId?: string): string {
const spreadsheetValidation = validateMicrosoftGraphId(spreadsheetId, 'spreadsheetId')
if (!spreadsheetValidation.isValid) {
throw new Error(spreadsheetValidation.error)
}

if (driveId) {
const validation = validateAlphanumericId(driveId, 'driveId')
if (!validation.isValid) {
throw new Error(validation.error)
const driveValidation = validateAlphanumericId(driveId, 'driveId')
Comment thread
waleedlatif1 marked this conversation as resolved.
Outdated
if (!driveValidation.isValid) {
throw new Error(driveValidation.error)
}
return `https://graph.microsoft.com/v1.0/drives/${driveId}/items/${spreadsheetId}`
Comment thread
waleedlatif1 marked this conversation as resolved.
}
Expand Down
Loading