Skip to content

Commit 2f4995b

Browse files
author
aadamgough
committed
fixed vulnerability and lint
1 parent 77dc563 commit 2f4995b

File tree

6 files changed

+80
-29
lines changed

6 files changed

+80
-29
lines changed

apps/sim/lib/oauth/oauth.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import {
2828
SalesforceIcon,
2929
SlackIcon,
3030
SnowflakeIcon,
31-
SupabaseIcon,
3231
TrelloIcon,
3332
WealthboxIcon,
3433
WebflowIcon,

apps/sim/tools/registry.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -770,20 +770,6 @@ import {
770770
updateIssueTool,
771771
updateProjectTool,
772772
} from '@/tools/sentry'
773-
import {
774-
snowflakeDescribeTableTool,
775-
snowflakeExecuteQueryTool,
776-
snowflakeInsertRowsTool,
777-
snowflakeUpdateRowsTool,
778-
snowflakeDeleteRowsTool,
779-
snowflakeListDatabasesTool,
780-
snowflakeListSchemasTool,
781-
snowflakeListTablesTool,
782-
snowflakeListViewsTool,
783-
snowflakeListWarehousesTool,
784-
snowflakeListFileFormatsTool,
785-
snowflakeListStagesTool,
786-
} from '@/tools/snowflake'
787773
import { searchTool as serperSearch } from '@/tools/serper'
788774
import {
789775
sharepointAddListItemTool,
@@ -805,6 +791,20 @@ import {
805791
slackUpdateMessageTool,
806792
} from '@/tools/slack'
807793
import { smsSendTool } from '@/tools/sms'
794+
import {
795+
snowflakeDeleteRowsTool,
796+
snowflakeDescribeTableTool,
797+
snowflakeExecuteQueryTool,
798+
snowflakeInsertRowsTool,
799+
snowflakeListDatabasesTool,
800+
snowflakeListFileFormatsTool,
801+
snowflakeListSchemasTool,
802+
snowflakeListStagesTool,
803+
snowflakeListTablesTool,
804+
snowflakeListViewsTool,
805+
snowflakeListWarehousesTool,
806+
snowflakeUpdateRowsTool,
807+
} from '@/tools/snowflake'
808808
import { stagehandAgentTool, stagehandExtractTool } from '@/tools/stagehand'
809809
import {
810810
stripeCancelPaymentIntentTool,

apps/sim/tools/snowflake/delete_rows.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type {
33
SnowflakeDeleteRowsParams,
44
SnowflakeDeleteRowsResponse,
55
} from '@/tools/snowflake/types'
6-
import { parseAccountUrl } from '@/tools/snowflake/utils'
6+
import { parseAccountUrl, sanitizeIdentifier, validateWhereClause } from '@/tools/snowflake/utils'
77
import type { ToolConfig } from '@/tools/types'
88

99
const logger = createLogger('SnowflakeDeleteRowsTool')
@@ -17,12 +17,15 @@ function buildDeleteSQL(
1717
table: string,
1818
whereClause?: string
1919
): string {
20-
const fullTableName = `${database}.${schema}.${table}`
20+
const sanitizedDatabase = sanitizeIdentifier(database)
21+
const sanitizedSchema = sanitizeIdentifier(schema)
22+
const sanitizedTable = sanitizeIdentifier(table)
23+
const fullTableName = `${sanitizedDatabase}.${sanitizedSchema}.${sanitizedTable}`
2124

2225
let sql = `DELETE FROM ${fullTableName}`
2326

24-
// Add WHERE clause if provided
2527
if (whereClause?.trim()) {
28+
validateWhereClause(whereClause)
2629
sql += ` WHERE ${whereClause}`
2730
}
2831

apps/sim/tools/snowflake/insert_rows.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import type {
33
SnowflakeInsertRowsParams,
44
SnowflakeInsertRowsResponse,
55
} from '@/tools/snowflake/types'
6-
import { parseAccountUrl } from '@/tools/snowflake/utils'
6+
import { parseAccountUrl, sanitizeIdentifier } from '@/tools/snowflake/utils'
77
import type { ToolConfig } from '@/tools/types'
88

99
const logger = createLogger('SnowflakeInsertRowsTool')
1010

1111
/**
12-
* Build INSERT SQL statement from parameters
12+
* Build INSERT SQL statement from parameters with proper identifier quoting
1313
*/
1414
function buildInsertSQL(
1515
database: string,
@@ -18,10 +18,13 @@ function buildInsertSQL(
1818
columns: string[],
1919
values: any[][]
2020
): string {
21-
const fullTableName = `${database}.${schema}.${table}`
22-
const columnList = columns.join(', ')
21+
const sanitizedDatabase = sanitizeIdentifier(database)
22+
const sanitizedSchema = sanitizeIdentifier(schema)
23+
const sanitizedTable = sanitizeIdentifier(table)
24+
const fullTableName = `${sanitizedDatabase}.${sanitizedSchema}.${sanitizedTable}`
25+
26+
const columnList = columns.map((col) => sanitizeIdentifier(col)).join(', ')
2327

24-
// Build values clause for multiple rows
2528
const valuesClause = values
2629
.map((rowValues) => {
2730
const formattedValues = rowValues.map((val) => {

apps/sim/tools/snowflake/update_rows.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import type {
33
SnowflakeUpdateRowsParams,
44
SnowflakeUpdateRowsResponse,
55
} from '@/tools/snowflake/types'
6-
import { parseAccountUrl } from '@/tools/snowflake/utils'
6+
import { parseAccountUrl, sanitizeIdentifier, validateWhereClause } from '@/tools/snowflake/utils'
77
import type { ToolConfig } from '@/tools/types'
88

99
const logger = createLogger('SnowflakeUpdateRowsTool')
1010

1111
/**
12-
* Build UPDATE SQL statement from parameters
12+
* Build UPDATE SQL statement from parameters with proper identifier quoting
1313
*/
1414
function buildUpdateSQL(
1515
database: string,
@@ -18,11 +18,15 @@ function buildUpdateSQL(
1818
updates: Record<string, any>,
1919
whereClause?: string
2020
): string {
21-
const fullTableName = `${database}.${schema}.${table}`
21+
const sanitizedDatabase = sanitizeIdentifier(database)
22+
const sanitizedSchema = sanitizeIdentifier(schema)
23+
const sanitizedTable = sanitizeIdentifier(table)
24+
const fullTableName = `${sanitizedDatabase}.${sanitizedSchema}.${sanitizedTable}`
2225

23-
// Build SET clause
2426
const setClause = Object.entries(updates)
2527
.map(([column, value]) => {
28+
const sanitizedColumn = sanitizeIdentifier(column)
29+
2630
let formattedValue: string
2731

2832
if (value === null || value === undefined) {
@@ -36,14 +40,14 @@ function buildUpdateSQL(
3640
formattedValue = String(value)
3741
}
3842

39-
return `${column} = ${formattedValue}`
43+
return `${sanitizedColumn} = ${formattedValue}`
4044
})
4145
.join(', ')
4246

4347
let sql = `UPDATE ${fullTableName} SET ${setClause}`
4448

45-
// Add WHERE clause if provided
4649
if (whereClause?.trim()) {
50+
validateWhereClause(whereClause)
4751
sql += ` WHERE ${whereClause}`
4852
}
4953

apps/sim/tools/snowflake/utils.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,45 @@ export function extractColumnMetadata(response: any): Array<{ name: string; type
140140
type: col.type,
141141
}))
142142
}
143+
144+
export function sanitizeIdentifier(identifier: string): string {
145+
if (identifier.includes('.')) {
146+
const parts = identifier.split('.')
147+
return parts.map((part) => sanitizeSingleIdentifier(part)).join('.')
148+
}
149+
150+
return sanitizeSingleIdentifier(identifier)
151+
}
152+
153+
export function validateWhereClause(where: string): void {
154+
const dangerousPatterns = [
155+
/;\s*(drop|delete|insert|update|create|alter|grant|revoke|truncate)/i,
156+
/union\s+select/i,
157+
/into\s+outfile/i,
158+
/load_file/i,
159+
/--/,
160+
/\/\*/,
161+
/\*\//,
162+
/xp_cmdshell/i,
163+
/exec\s*\(/i,
164+
/execute\s+immediate/i,
165+
]
166+
167+
for (const pattern of dangerousPatterns) {
168+
if (pattern.test(where)) {
169+
throw new Error('WHERE clause contains potentially dangerous operation')
170+
}
171+
}
172+
}
173+
174+
function sanitizeSingleIdentifier(identifier: string): string {
175+
const cleaned = identifier.replace(/"/g, '')
176+
177+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(cleaned)) {
178+
throw new Error(
179+
`Invalid identifier: ${identifier}. Identifiers must start with a letter or underscore and contain only letters, numbers, and underscores.`
180+
)
181+
}
182+
183+
return `"${cleaned}"`
184+
}

0 commit comments

Comments
 (0)