mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
fixed vulnerability and lint
This commit is contained in:
@@ -3,7 +3,7 @@ import type {
|
||||
SnowflakeDeleteRowsParams,
|
||||
SnowflakeDeleteRowsResponse,
|
||||
} from '@/tools/snowflake/types'
|
||||
import { parseAccountUrl } from '@/tools/snowflake/utils'
|
||||
import { parseAccountUrl, sanitizeIdentifier, validateWhereClause } from '@/tools/snowflake/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('SnowflakeDeleteRowsTool')
|
||||
@@ -17,12 +17,15 @@ function buildDeleteSQL(
|
||||
table: string,
|
||||
whereClause?: string
|
||||
): string {
|
||||
const fullTableName = `${database}.${schema}.${table}`
|
||||
const sanitizedDatabase = sanitizeIdentifier(database)
|
||||
const sanitizedSchema = sanitizeIdentifier(schema)
|
||||
const sanitizedTable = sanitizeIdentifier(table)
|
||||
const fullTableName = `${sanitizedDatabase}.${sanitizedSchema}.${sanitizedTable}`
|
||||
|
||||
let sql = `DELETE FROM ${fullTableName}`
|
||||
|
||||
// Add WHERE clause if provided
|
||||
if (whereClause?.trim()) {
|
||||
validateWhereClause(whereClause)
|
||||
sql += ` WHERE ${whereClause}`
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@ import type {
|
||||
SnowflakeInsertRowsParams,
|
||||
SnowflakeInsertRowsResponse,
|
||||
} from '@/tools/snowflake/types'
|
||||
import { parseAccountUrl } from '@/tools/snowflake/utils'
|
||||
import { parseAccountUrl, sanitizeIdentifier } from '@/tools/snowflake/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('SnowflakeInsertRowsTool')
|
||||
|
||||
/**
|
||||
* Build INSERT SQL statement from parameters
|
||||
* Build INSERT SQL statement from parameters with proper identifier quoting
|
||||
*/
|
||||
function buildInsertSQL(
|
||||
database: string,
|
||||
@@ -18,10 +18,13 @@ function buildInsertSQL(
|
||||
columns: string[],
|
||||
values: any[][]
|
||||
): string {
|
||||
const fullTableName = `${database}.${schema}.${table}`
|
||||
const columnList = columns.join(', ')
|
||||
const sanitizedDatabase = sanitizeIdentifier(database)
|
||||
const sanitizedSchema = sanitizeIdentifier(schema)
|
||||
const sanitizedTable = sanitizeIdentifier(table)
|
||||
const fullTableName = `${sanitizedDatabase}.${sanitizedSchema}.${sanitizedTable}`
|
||||
|
||||
const columnList = columns.map((col) => sanitizeIdentifier(col)).join(', ')
|
||||
|
||||
// Build values clause for multiple rows
|
||||
const valuesClause = values
|
||||
.map((rowValues) => {
|
||||
const formattedValues = rowValues.map((val) => {
|
||||
|
||||
@@ -3,13 +3,13 @@ import type {
|
||||
SnowflakeUpdateRowsParams,
|
||||
SnowflakeUpdateRowsResponse,
|
||||
} from '@/tools/snowflake/types'
|
||||
import { parseAccountUrl } from '@/tools/snowflake/utils'
|
||||
import { parseAccountUrl, sanitizeIdentifier, validateWhereClause } from '@/tools/snowflake/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('SnowflakeUpdateRowsTool')
|
||||
|
||||
/**
|
||||
* Build UPDATE SQL statement from parameters
|
||||
* Build UPDATE SQL statement from parameters with proper identifier quoting
|
||||
*/
|
||||
function buildUpdateSQL(
|
||||
database: string,
|
||||
@@ -18,11 +18,15 @@ function buildUpdateSQL(
|
||||
updates: Record<string, any>,
|
||||
whereClause?: string
|
||||
): string {
|
||||
const fullTableName = `${database}.${schema}.${table}`
|
||||
const sanitizedDatabase = sanitizeIdentifier(database)
|
||||
const sanitizedSchema = sanitizeIdentifier(schema)
|
||||
const sanitizedTable = sanitizeIdentifier(table)
|
||||
const fullTableName = `${sanitizedDatabase}.${sanitizedSchema}.${sanitizedTable}`
|
||||
|
||||
// Build SET clause
|
||||
const setClause = Object.entries(updates)
|
||||
.map(([column, value]) => {
|
||||
const sanitizedColumn = sanitizeIdentifier(column)
|
||||
|
||||
let formattedValue: string
|
||||
|
||||
if (value === null || value === undefined) {
|
||||
@@ -36,14 +40,14 @@ function buildUpdateSQL(
|
||||
formattedValue = String(value)
|
||||
}
|
||||
|
||||
return `${column} = ${formattedValue}`
|
||||
return `${sanitizedColumn} = ${formattedValue}`
|
||||
})
|
||||
.join(', ')
|
||||
|
||||
let sql = `UPDATE ${fullTableName} SET ${setClause}`
|
||||
|
||||
// Add WHERE clause if provided
|
||||
if (whereClause?.trim()) {
|
||||
validateWhereClause(whereClause)
|
||||
sql += ` WHERE ${whereClause}`
|
||||
}
|
||||
|
||||
|
||||
@@ -140,3 +140,45 @@ export function extractColumnMetadata(response: any): Array<{ name: string; type
|
||||
type: col.type,
|
||||
}))
|
||||
}
|
||||
|
||||
export function sanitizeIdentifier(identifier: string): string {
|
||||
if (identifier.includes('.')) {
|
||||
const parts = identifier.split('.')
|
||||
return parts.map((part) => sanitizeSingleIdentifier(part)).join('.')
|
||||
}
|
||||
|
||||
return sanitizeSingleIdentifier(identifier)
|
||||
}
|
||||
|
||||
export function validateWhereClause(where: string): void {
|
||||
const dangerousPatterns = [
|
||||
/;\s*(drop|delete|insert|update|create|alter|grant|revoke|truncate)/i,
|
||||
/union\s+select/i,
|
||||
/into\s+outfile/i,
|
||||
/load_file/i,
|
||||
/--/,
|
||||
/\/\*/,
|
||||
/\*\//,
|
||||
/xp_cmdshell/i,
|
||||
/exec\s*\(/i,
|
||||
/execute\s+immediate/i,
|
||||
]
|
||||
|
||||
for (const pattern of dangerousPatterns) {
|
||||
if (pattern.test(where)) {
|
||||
throw new Error('WHERE clause contains potentially dangerous operation')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sanitizeSingleIdentifier(identifier: string): string {
|
||||
const cleaned = identifier.replace(/"/g, '')
|
||||
|
||||
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(cleaned)) {
|
||||
throw new Error(
|
||||
`Invalid identifier: ${identifier}. Identifiers must start with a letter or underscore and contain only letters, numbers, and underscores.`
|
||||
)
|
||||
}
|
||||
|
||||
return `"${cleaned}"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user