Bugfix/arbitrary create attachemnt file upload (#4171)
fix arbitrary create attachemnt file upload
This commit is contained in:
parent
c6968ff385
commit
c2b830f279
|
|
@ -4,7 +4,6 @@ import { ListKeyOptions, RecordManagerInterface, UpdateOptions } from '@langchai
|
|||
import { DataSource } from 'typeorm'
|
||||
import { getHost, getSSL } from '../../vectorstores/Postgres/utils'
|
||||
import { getDatabase, getPort, getTableName } from './utils'
|
||||
import fs from 'fs'
|
||||
|
||||
const serverCredentialsExists = !!process.env.POSTGRES_RECORDMANAGER_USER && !!process.env.POSTGRES_RECORDMANAGER_PASSWORD
|
||||
|
||||
|
|
|
|||
|
|
@ -10,3 +10,4 @@ export * from './speechToText'
|
|||
export * from './storageUtils'
|
||||
export * from './handler'
|
||||
export * from './followUpPrompts'
|
||||
export * from './validator'
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export const addArrayFilesToStorage = async (mime: string, bf: Buffer, fileName:
|
|||
fileNames.push(sanitizedFilename)
|
||||
return 'FILE-STORAGE::' + JSON.stringify(fileNames)
|
||||
} else {
|
||||
const dir = path.join(getStoragePath(), ...paths)
|
||||
const dir = path.join(getStoragePath(), ...paths.map(_sanitizeFilename))
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true })
|
||||
}
|
||||
|
|
@ -110,7 +110,7 @@ export const addSingleFileToStorage = async (mime: string, bf: Buffer, fileName:
|
|||
await s3Client.send(putObjCmd)
|
||||
return 'FILE-STORAGE::' + sanitizedFilename
|
||||
} else {
|
||||
const dir = path.join(getStoragePath(), ...paths)
|
||||
const dir = path.join(getStoragePath(), ...paths.map(_sanitizeFilename))
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true })
|
||||
}
|
||||
|
|
@ -180,7 +180,7 @@ export const getFileFromStorage = async (file: string, ...paths: string[]): Prom
|
|||
const buffer = Buffer.concat(response.Body.toArray())
|
||||
return buffer
|
||||
} else {
|
||||
const fileInStorage = path.join(getStoragePath(), ...paths, sanitizedFilename)
|
||||
const fileInStorage = path.join(getStoragePath(), ...paths.map(_sanitizeFilename), sanitizedFilename)
|
||||
return fs.readFileSync(fileInStorage)
|
||||
}
|
||||
}
|
||||
|
|
@ -209,7 +209,7 @@ export const removeFilesFromStorage = async (...paths: string[]) => {
|
|||
}
|
||||
await _deleteS3Folder(Key)
|
||||
} else {
|
||||
const directory = path.join(getStoragePath(), ...paths)
|
||||
const directory = path.join(getStoragePath(), ...paths.map(_sanitizeFilename))
|
||||
_deleteLocalFolderRecursive(directory)
|
||||
}
|
||||
}
|
||||
|
|
@ -243,7 +243,7 @@ export const removeSpecificFileFromStorage = async (...paths: string[]) => {
|
|||
const sanitizedFilename = _sanitizeFilename(fileName)
|
||||
paths.push(sanitizedFilename)
|
||||
}
|
||||
const file = path.join(getStoragePath(), ...paths)
|
||||
const file = path.join(getStoragePath(), ...paths.map(_sanitizeFilename))
|
||||
fs.unlinkSync(file)
|
||||
}
|
||||
}
|
||||
|
|
@ -258,7 +258,7 @@ export const removeFolderFromStorage = async (...paths: string[]) => {
|
|||
}
|
||||
await _deleteS3Folder(Key)
|
||||
} else {
|
||||
const directory = path.join(getStoragePath(), ...paths)
|
||||
const directory = path.join(getStoragePath(), ...paths.map(_sanitizeFilename))
|
||||
_deleteLocalFolderRecursive(directory, true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Validates if a string is a valid UUID v4
|
||||
* @param {string} uuid The string to validate
|
||||
* @returns {boolean} True if valid UUID, false otherwise
|
||||
*/
|
||||
export const isValidUUID = (uuid: string): boolean => {
|
||||
// UUID v4 regex pattern
|
||||
const uuidV4Pattern = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
||||
return uuidV4Pattern.test(uuid)
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if a string contains path traversal attempts
|
||||
* @param {string} path The string to validate
|
||||
* @returns {boolean} True if path traversal detected, false otherwise
|
||||
*/
|
||||
export const isPathTraversal = (path: string): boolean => {
|
||||
// Check for common path traversal patterns
|
||||
const dangerousPatterns = [
|
||||
'..', // Directory traversal
|
||||
'/', // Root directory
|
||||
'\\', // Windows root directory
|
||||
'%2e', // URL encoded .
|
||||
'%2f', // URL encoded /
|
||||
'%5c' // URL encoded \
|
||||
]
|
||||
|
||||
return dangerousPatterns.some((pattern) => path.toLowerCase().includes(pattern))
|
||||
}
|
||||
|
|
@ -6,10 +6,15 @@ import {
|
|||
IDocument,
|
||||
mapExtToInputField,
|
||||
mapMimeTypeToInputField,
|
||||
removeSpecificFileFromUpload
|
||||
removeSpecificFileFromUpload,
|
||||
isValidUUID,
|
||||
isPathTraversal
|
||||
} from 'flowise-components'
|
||||
import { getRunningExpressApp } from './getRunningExpressApp'
|
||||
import { getErrorMessage } from '../errors/utils'
|
||||
import { InternalFlowiseError } from '../errors/internalFlowiseError'
|
||||
import { StatusCodes } from 'http-status-codes'
|
||||
import { ChatFlow } from '../database/entities/ChatFlow'
|
||||
|
||||
/**
|
||||
* Create attachment
|
||||
|
|
@ -19,17 +24,26 @@ export const createFileAttachment = async (req: Request) => {
|
|||
const appServer = getRunningExpressApp()
|
||||
|
||||
const chatflowid = req.params.chatflowId
|
||||
if (!chatflowid) {
|
||||
throw new Error(
|
||||
'Params chatflowId is required! Please provide chatflowId and chatId in the URL: /api/v1/attachments/:chatflowId/:chatId'
|
||||
)
|
||||
if (!chatflowid || !isValidUUID(chatflowid)) {
|
||||
throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, 'Invalid chatflowId format - must be a valid UUID')
|
||||
}
|
||||
|
||||
const chatId = req.params.chatId
|
||||
if (!chatId) {
|
||||
throw new Error(
|
||||
'Params chatId is required! Please provide chatflowId and chatId in the URL: /api/v1/attachments/:chatflowId/:chatId'
|
||||
)
|
||||
if (!chatId || !isValidUUID(chatId)) {
|
||||
throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, 'Invalid chatId format - must be a valid UUID')
|
||||
}
|
||||
|
||||
// Check for path traversal attempts
|
||||
if (isPathTraversal(chatflowid) || isPathTraversal(chatId)) {
|
||||
throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, 'Invalid path characters detected')
|
||||
}
|
||||
|
||||
// Validate chatflow exists and check API key
|
||||
const chatflow = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({
|
||||
id: chatflowid
|
||||
})
|
||||
if (!chatflow) {
|
||||
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Chatflow ${chatflowid} not found`)
|
||||
}
|
||||
|
||||
// Find FileLoader node
|
||||
|
|
|
|||
Loading…
Reference in New Issue