Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
11 changes: 11 additions & 0 deletions packages/components/evaluation/EvaluationRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ export class EvaluationRunner {

public async runEvaluations(data: ICommonObject) {
const chatflowIds = JSON.parse(data.chatflowId)

// Validate chatflowIds is an actual array to prevent DoS attacks
if (!Array.isArray(chatflowIds)) {
throw new Error('chatflowId must be a valid array')
}

// Validate dataset.rows is an actual array to prevent DoS attacks
if (!data.dataset || !Array.isArray(data.dataset.rows)) {
throw new Error('dataset.rows must be a valid array')
}

const returnData: ICommonObject = {}
returnData.evaluationId = data.evaluationId
returnData.runDate = new Date()
Expand Down
5 changes: 5 additions & 0 deletions packages/server/src/services/evaluations/EvaluatorRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ export const runAdditionalEvaluators = async (
selectedEvaluators: string[],
workspaceId: string
) => {
// Validate inputs are arrays and enforce size limits
if (!Array.isArray(actualOutputArray) || !Array.isArray(selectedEvaluators)) {
throw new Error('Invalid input: expected arrays')
}
Comment thread
christopherholland-workday marked this conversation as resolved.
Outdated

const evaluationResults: any[] = []
const evaluatorDict: any = {}

Expand Down
33 changes: 28 additions & 5 deletions packages/server/src/services/evaluations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,31 @@ const createEvaluation = async (body: ICommonObject, baseURL: string, orgId: str
const row = appServer.AppDataSource.getRepository(Evaluation).create(newEval)
row.average_metrics = JSON.stringify({})

// Parse and validate evaluator arrays to prevent DoS attacks
const chatflowTypes = body.chatflowType ? JSON.parse(body.chatflowType) : []
if (!Array.isArray(chatflowTypes)) {
throw new Error('chatflowType must be a valid array')
}

const simpleEvaluators = body.selectedSimpleEvaluators.length > 0 ? JSON.parse(body.selectedSimpleEvaluators) : []
Comment thread
christopherholland-workday marked this conversation as resolved.
Outdated
if (!Array.isArray(simpleEvaluators)) {
throw new Error('selectedSimpleEvaluators must be a valid array')
}

const additionalConfig: ICommonObject = {
chatflowTypes: body.chatflowType ? JSON.parse(body.chatflowType) : [],
chatflowTypes: chatflowTypes,
datasetAsOneConversation: body.datasetAsOneConversation,
simpleEvaluators: body.selectedSimpleEvaluators.length > 0 ? JSON.parse(body.selectedSimpleEvaluators) : []
simpleEvaluators: simpleEvaluators
}

if (body.evaluationType === 'llm') {
additionalConfig.lLMEvaluators = body.selectedLLMEvaluators.length > 0 ? JSON.parse(body.selectedLLMEvaluators) : []
const lLMEvaluators = body.selectedLLMEvaluators.length > 0 ? JSON.parse(body.selectedLLMEvaluators) : []
Comment thread
christopherholland-workday marked this conversation as resolved.
Outdated

if (!Array.isArray(lLMEvaluators)) {
throw new Error('selectedLLMEvaluators must be a valid array')
}

additionalConfig.lLMEvaluators = lLMEvaluators
Comment on lines +75 to +100
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There's repetition in parsing and validating arrays from the request body (chatflowTypes, simpleEvaluators, lLMEvaluators). To improve code clarity and maintainability, consider extracting this logic into a helper function. This would also be a good place to handle potential JSON.parse errors with a try-catch block for more specific error messages.

Example:
const parseJsonArray = (input: string | undefined, fieldName: string): any[] => {
if (!input) {
return [];
}
try {
const parsed = JSON.parse(input);
if (!Array.isArray(parsed)) {
throw new Error(${fieldName} must be a valid array);
}
return parsed;
} catch (e) {
throw new Error(Invalid JSON for ${fieldName}: ${e.message});
}
};

References
  1. Prioritize code readability and understandability over conciseness. A series of simple, chained operations can be preferable to a single, more complex one if it improves understandability and reduces the potential for future errors.

additionalConfig.llmConfig = {
credentialId: body.credentialId,
llm: body.llm,
Expand Down Expand Up @@ -123,6 +140,12 @@ const createEvaluation = async (body: ICommonObject, baseURL: string, orgId: str
// When chatflow has an APIKey
const apiKeys: { chatflowId: string; apiKey: string }[] = []
const chatflowIds = JSON.parse(body.chatflowId)

// Validate chatflowIds is an actual array to prevent DoS attacks
if (!Array.isArray(chatflowIds)) {
throw new Error('chatflowId must be a valid array')
}

for (let i = 0; i < chatflowIds.length; i++) {
const chatflowId = chatflowIds[i]
const cFlow = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({
Expand Down Expand Up @@ -246,7 +269,7 @@ const createEvaluation = async (body: ICommonObject, baseURL: string, orgId: str
metricsArray,
actualOutputArray,
errorArray,
body.selectedSimpleEvaluators.length > 0 ? JSON.parse(body.selectedSimpleEvaluators) : [],
additionalConfig.simpleEvaluators,
workspaceId
)

Expand All @@ -257,7 +280,7 @@ const createEvaluation = async (body: ICommonObject, baseURL: string, orgId: str

if (body.evaluationType === 'llm') {
resultRow.llmConfig = additionalConfig.llmConfig
resultRow.LLMEvaluators = body.selectedLLMEvaluators.length > 0 ? JSON.parse(body.selectedLLMEvaluators) : []
resultRow.LLMEvaluators = additionalConfig.lLMEvaluators
const llmEvaluatorMap: { evaluatorId: string; evaluator: any }[] = []
for (let i = 0; i < resultRow.LLMEvaluators.length; i++) {
const evaluatorId = resultRow.LLMEvaluators[i]
Expand Down
Loading