Add protections for loop-bound injections#5773
Add protections for loop-bound injections#5773christopherholland-workday merged 1 commit intomainfrom
Conversation
Summary of ChangesHello @christopherholland-workday, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the application's security posture by introducing comprehensive input validation and array size limitations across several key evaluation-related functions. The changes aim to prevent Denial of Service vulnerabilities that could arise from processing unusually large or malformed data inputs, thereby improving the stability and resilience of the evaluation system. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request significantly enhances the application's resilience against Denial of Service (DoS) attacks by implementing robust input validation for array lengths and types. The introduction of MAX_ constants across EvaluationRunner.ts and EvaluatorRunner.ts, along with the corresponding checks, effectively limits the processing of excessively large inputs. This is a crucial step towards improving the overall security and stability of the evaluation services.
| @@ -88,6 +88,27 @@ export class EvaluationRunner { | |||
|
|
|||
| public async runEvaluations(data: ICommonObject) { | |||
| const chatflowIds = JSON.parse(data.chatflowId) | |||
There was a problem hiding this comment.
The JSON.parse operation can throw an error if data.chatflowId is not a valid JSON string, leading to a generic parsing error. Wrapping this in a try-catch block would allow for a more specific and user-friendly error message, clearly indicating that the input format is incorrect.
| const chatflowIds = JSON.parse(data.chatflowId) | |
| let chatflowIds: string[]; | |
| try { | |
| chatflowIds = JSON.parse(data.chatflowId); | |
| } catch (e) { | |
| throw new Error('chatflowId must be a valid JSON array string'); | |
| } |
| @@ -103,6 +121,11 @@ export const runAdditionalEvaluators = async ( | |||
| case 'ContainsAny': | |||
| passed = false | |||
| splitValues = value.split(',').map((v) => v.trim().toLowerCase()) // Split, trim, and convert to lowercase | |||
There was a problem hiding this comment.
While the MAX_SPLIT_VALUES check is in place, the split and map operations are performed on the entire value string first. If value is extremely long and contains many delimiters, these operations could consume significant memory and CPU before the length check. For extreme edge cases, consider a more memory-efficient way to count or process elements, or validate the raw string length before splitting.
| row.average_metrics = JSON.stringify({}) | ||
|
|
||
| // Parse and validate evaluator arrays to prevent DoS attacks | ||
| const chatflowTypes = body.chatflowType ? JSON.parse(body.chatflowType) : [] |
There was a problem hiding this comment.
Similar to other JSON.parse calls, if body.chatflowType is provided but is not a valid JSON string, JSON.parse will throw an error. Implementing a try-catch block here would provide a more precise error message to the user about the expected JSON format.
| const chatflowTypes = body.chatflowType ? JSON.parse(body.chatflowType) : [] | |
| let chatflowTypes: string[]; | |
| try { | |
| chatflowTypes = body.chatflowType ? JSON.parse(body.chatflowType) : []; | |
| } catch (e) { | |
| throw new Error('chatflowType must be a valid JSON array string'); | |
| } |
| throw new Error(`Cannot evaluate more than ${MAX_CHATFLOW_TYPES} chatflow types at once`) | ||
| } | ||
|
|
||
| const simpleEvaluators = body.selectedSimpleEvaluators.length > 0 ? JSON.parse(body.selectedSimpleEvaluators) : [] |
There was a problem hiding this comment.
To provide a clearer error message in case body.selectedSimpleEvaluators is not a valid JSON string, it's recommended to wrap the JSON.parse call in a try-catch block.
| const simpleEvaluators = body.selectedSimpleEvaluators.length > 0 ? JSON.parse(body.selectedSimpleEvaluators) : [] | |
| let simpleEvaluators: string[]; | |
| try { | |
| simpleEvaluators = body.selectedSimpleEvaluators.length > 0 ? JSON.parse(body.selectedSimpleEvaluators) : []; | |
| } catch (e) { | |
| throw new Error('selectedSimpleEvaluators must be a valid JSON array string'); | |
| } |
|
|
||
| if (body.evaluationType === 'llm') { | ||
| additionalConfig.lLMEvaluators = body.selectedLLMEvaluators.length > 0 ? JSON.parse(body.selectedLLMEvaluators) : [] | ||
| const lLMEvaluators = body.selectedLLMEvaluators.length > 0 ? JSON.parse(body.selectedLLMEvaluators) : [] |
There was a problem hiding this comment.
For improved error handling, consider adding a try-catch block around the JSON.parse call for body.selectedLLMEvaluators. This would allow for a more specific error message if the input is not valid JSON.
let lLMEvaluators: string[];
try {
lLMEvaluators = body.selectedLLMEvaluators.length > 0 ? JSON.parse(body.selectedLLMEvaluators) : [];
} catch (e) {
throw new Error('selectedLLMEvaluators must be a valid JSON array string');
}| @@ -123,6 +153,17 @@ 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) | |||
There was a problem hiding this comment.
Similar to other JSON.parse operations, if body.chatflowId is not a valid JSON string, a generic parsing error will occur. A try-catch block would enable a more informative error message for invalid JSON input.
let chatflowIds: string[];
try {
chatflowIds = JSON.parse(body.chatflowId);
} catch (e) {
throw new Error('chatflowId must be a valid JSON array string');
}|
im not a fan of hardcoding limit to prevent DoS. Since |
|
Not sure why this says it was merged, it is not in the history: https://github.com/FlowiseAI/Flowise/pulls?q=is%3Apr+is%3Aclosed And I did not merge it |
Adding checks to prevent DoS due to large loop boundaries.