Conversation
Signed-off-by: dev-callgent <dev@callgent.com>
refactor: rename to callgent
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
User as a service
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
User as a service
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
upgrade node version dependency Signed-off-by: ahlon <ahlon2002@gmail.com>
add run tests in devlog Signed-off-by: ahlon <ahlon2002@gmail.com>
update devlog Signed-off-by: ahlon <ahlon2002@gmail.com>
Signed-off-by: ZhaoYongchao <zhao.yc@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
docs: rename mailHost
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
…into feature/hub Signed-off-by: root <root@zyc>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: ZhaoYongchao <152259278+ZhaoYongchao@users.noreply.github.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: root <16632301768@163.com>
Signed-off-by: ZhaoYongchao <152259278+ZhaoYongchao@users.noreply.github.com>
Signed-off-by: ZhaoYongchao <152259278+ZhaoYongchao@users.noreply.github.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: root <16632301768@163.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Signed-off-by: dev-callgent <dev@callgent.com>
Feature/hub
| `type conflict, cannot merge, src: ${JSON.stringify(val[0])}, target: ${JSON.stringify(target[key][0])}`, | ||
| ); | ||
| else this._deepMerge(target[key][0], val[0]); | ||
| } else target[key] = val; |
Check warning
Code scanning / CodeQL
Prototype-polluting function Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the prototype pollution issue in the _deepMerge function, we need to ensure that the function does not copy the special properties __proto__ and constructor. Additionally, we should ensure that only own properties of the target object are merged recursively.
- Modify the
_deepMergefunction to skip the properties__proto__andconstructor. - Ensure that only own properties of the
targetobject are merged recursively.
| @@ -299,4 +299,4 @@ | ||
| Object.entries(source).forEach(([key, val]) => { | ||
| if (!val) return; | ||
| if (target[key]) { | ||
| if (!val || key === '__proto__' || key === 'constructor') return; | ||
| if (Object.prototype.hasOwnProperty.call(target, key)) { | ||
| if (typeof val === 'object') { |
| } else target[key] = val; | ||
| } | ||
| } else if (typeof target[key] !== 'object') | ||
| target[key] = val; // type conflict |
Check warning
Code scanning / CodeQL
Prototype-polluting function Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the prototype pollution issue, we need to ensure that the _deepMerge function does not allow the special properties __proto__ and constructor to be copied from the source object to the target object. This can be achieved by adding a check to skip these properties during the merge process.
| @@ -300,2 +300,3 @@ | ||
| if (!val) return; | ||
| if (key === '__proto__' || key === 'constructor') return; | ||
| if (target[key]) { |
| target[key] = val; // type conflict | ||
| else this._deepMerge(target[key], val); | ||
| } else target[key] = val; | ||
| } else target[key] = val; |
Check warning
Code scanning / CodeQL
Prototype-polluting function Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the prototype pollution issue, we need to ensure that the _deepMerge function does not allow properties like __proto__ and constructor to be copied from the source object to the target object. Additionally, we should ensure that only own properties of the source object are copied.
The best way to fix this is to:
- Add a check to skip properties named
__proto__andconstructor. - Ensure that only own properties of the
sourceobject are copied.
| @@ -299,3 +299,4 @@ | ||
| Object.entries(source).forEach(([key, val]) => { | ||
| if (!val) return; | ||
| if (!val || !Object.prototype.hasOwnProperty.call(source, key)) return; | ||
| if (key === '__proto__' || key === 'constructor') return; | ||
| if (target[key]) { |
| protected _getTaskId(taskId: string) { | ||
| let sp = taskId?.split('-'); | ||
| if ( | ||
| !(taskId?.length == this.id.length + 7) || |
Check failure
Code scanning / CodeQL
Type confusion through parameter tampering Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the problem, we need to ensure that the taskId parameter is a string before it is used in the _getTaskId method. This can be done by adding a type check in the EventObject constructor. If the taskId is not a string, we can handle it appropriately, such as by throwing an error or setting a default value.
| @@ -10,3 +10,3 @@ | ||
| public readonly dataType: string, | ||
| taskId: string, | ||
| taskId: any, | ||
| public readonly title: string, | ||
| @@ -20,2 +20,5 @@ | ||
|
|
||
| if (typeof taskId !== 'string') { | ||
| throw new Error('Invalid taskId: must be a string'); | ||
| } | ||
| this.taskId = this._getTaskId(taskId); |
| @@ -115,3 +115,3 @@ | ||
| requirement, | ||
| taskId, | ||
| typeof taskId === 'string' ? taskId : '', | ||
| title, |
| /** move files into dir, overwrite existing */ | ||
| async move(files: File[], dir: string): Promise<RequestFile[]> { | ||
| if (!files?.length) return; | ||
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the problem, we need to ensure that the constructed file paths are contained within a safe root directory. This can be achieved by normalizing the path using path.resolve and then checking that the normalized path starts with the root directory. If the path is not within the root directory, we should reject the operation.
- Normalize the
dirparameter usingpath.resolve. - Check that the normalized path starts with the root directory (
this.UPLOAD_BASE_DIR). - If the check fails, throw an error or handle it appropriately.
| @@ -29,6 +29,10 @@ | ||
| if (!files?.length) return; | ||
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); | ||
| const resolvedDir = path.resolve(this.UPLOAD_BASE_DIR, dir); | ||
| if (!resolvedDir.startsWith(this.UPLOAD_BASE_DIR)) { | ||
| throw new Error('Invalid directory path'); | ||
| } | ||
| if (!fs.existsSync(resolvedDir)) fs.mkdirSync(resolvedDir, { recursive: true }); | ||
|
|
||
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| const newPath = path.join(resolvedDir, f.originalname); | ||
| if (fs.existsSync(newPath)) fs.unlinkSync(newPath); | ||
| @@ -50,6 +54,10 @@ | ||
| if (!files?.length) return; | ||
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); | ||
| const resolvedDir = path.resolve(this.UPLOAD_BASE_DIR, dir); | ||
| if (!resolvedDir.startsWith(this.UPLOAD_BASE_DIR)) { | ||
| throw new Error('Invalid directory path'); | ||
| } | ||
| if (!fs.existsSync(resolvedDir)) fs.mkdirSync(resolvedDir, { recursive: true }); | ||
|
|
||
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| const newPath = path.join(resolvedDir, f.originalname); | ||
| fs.copyFileSync(f.path, newPath); |
|
|
||
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| if (fs.existsSync(newPath)) fs.unlinkSync(newPath); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the problem, we need to ensure that the constructed file paths are contained within a safe root directory. This can be achieved by normalizing the path using path.resolve and then checking that the normalized path starts with the root directory. If the path is not within the root directory, we should reject the operation.
- Normalize the
dirparameter usingpath.resolve. - Check that the normalized path starts with the
UPLOAD_BASE_DIR. - If the check fails, throw an error or handle it appropriately.
| @@ -29,6 +29,10 @@ | ||
| if (!files?.length) return; | ||
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); | ||
| const normalizedDir = path.resolve(this.UPLOAD_BASE_DIR, dir); | ||
| if (!normalizedDir.startsWith(this.UPLOAD_BASE_DIR)) { | ||
| throw new Error('Invalid directory path'); | ||
| } | ||
| if (!fs.existsSync(normalizedDir)) fs.mkdirSync(normalizedDir, { recursive: true }); | ||
|
|
||
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| const newPath = path.join(normalizedDir, f.originalname); | ||
| if (fs.existsSync(newPath)) fs.unlinkSync(newPath); | ||
| @@ -50,6 +54,10 @@ | ||
| if (!files?.length) return; | ||
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); | ||
| const normalizedDir = path.resolve(this.UPLOAD_BASE_DIR, dir); | ||
| if (!normalizedDir.startsWith(this.UPLOAD_BASE_DIR)) { | ||
| throw new Error('Invalid directory path'); | ||
| } | ||
| if (!fs.existsSync(normalizedDir)) fs.mkdirSync(normalizedDir, { recursive: true }); | ||
|
|
||
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| const newPath = path.join(normalizedDir, f.originalname); | ||
| fs.copyFileSync(f.path, newPath); |
|
|
||
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| if (fs.existsSync(newPath)) fs.unlinkSync(newPath); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the problem, we need to ensure that the dir parameter is properly sanitized before being used in file system operations. We can achieve this by normalizing the path and ensuring it is contained within a safe root directory. This involves using path.resolve to remove any ".." segments and then checking that the resulting path starts with the root directory.
- Normalize the
dirparameter usingpath.resolve. - Check that the normalized path starts with the
UPLOAD_BASE_DIR. - If the check fails, throw an error or handle it appropriately.
| @@ -29,6 +29,10 @@ | ||
| if (!files?.length) return; | ||
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); | ||
| const safeDir = path.resolve(this.UPLOAD_BASE_DIR, dir); | ||
| if (!safeDir.startsWith(this.UPLOAD_BASE_DIR)) { | ||
| throw new Error('Invalid directory path'); | ||
| } | ||
| if (!fs.existsSync(safeDir)) fs.mkdirSync(safeDir, { recursive: true }); | ||
|
|
||
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| const newPath = path.join(safeDir, f.originalname); | ||
| if (fs.existsSync(newPath)) fs.unlinkSync(newPath); |
| @@ -128,6 +128,11 @@ | ||
| e.context.callgent = callgent; | ||
| requirement.files = await this.filesService.move( | ||
| tmpFiles, | ||
| path.join(e.getTaskCwd(this.filesService.UPLOAD_BASE_DIR), 'upload'), | ||
| ); | ||
| try { | ||
| requirement.files = await this.filesService.move( | ||
| tmpFiles, | ||
| path.join(e.getTaskCwd(this.filesService.UPLOAD_BASE_DIR), 'upload'), | ||
| ); | ||
| } catch (error) { | ||
| res.status(400).send({ message: error.message }); | ||
| return; | ||
| } | ||
|
|
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| if (fs.existsSync(newPath)) fs.unlinkSync(newPath); | ||
| fs.renameSync(f.path, newPath); |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the problem, we need to ensure that the constructed file paths are validated and contained within a safe root directory. This can be achieved by normalizing the path using path.resolve and then checking that the normalized path starts with the root directory.
- Normalize the path using
path.resolveto remove any ".." segments. - Check that the normalized path starts with the root directory.
- If the path is not valid, handle the error appropriately (e.g., by throwing an exception or returning an error response).
| @@ -29,6 +29,10 @@ | ||
| if (!files?.length) return; | ||
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); | ||
| const normalizedDir = path.resolve(this.UPLOAD_BASE_DIR, dir); | ||
| if (!normalizedDir.startsWith(this.UPLOAD_BASE_DIR)) { | ||
| throw new Error('Invalid directory path'); | ||
| } | ||
| if (!fs.existsSync(normalizedDir)) fs.mkdirSync(normalizedDir, { recursive: true }); | ||
|
|
||
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| const newPath = path.join(normalizedDir, f.originalname); | ||
| if (fs.existsSync(newPath)) fs.unlinkSync(newPath); | ||
| @@ -50,6 +54,10 @@ | ||
| if (!files?.length) return; | ||
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); | ||
| const normalizedDir = path.resolve(this.UPLOAD_BASE_DIR, dir); | ||
| if (!normalizedDir.startsWith(this.UPLOAD_BASE_DIR)) { | ||
| throw new Error('Invalid directory path'); | ||
| } | ||
| if (!fs.existsSync(normalizedDir)) fs.mkdirSync(normalizedDir, { recursive: true }); | ||
|
|
||
| const result = files.map((f) => { | ||
| const newPath = path.join(dir, f.originalname); | ||
| const newPath = path.join(normalizedDir, f.originalname); | ||
| fs.copyFileSync(f.path, newPath); |
| } | ||
|
|
||
| static sleep(ms: number) { | ||
| return new Promise((resolve) => setTimeout(resolve, ms)); |
Check failure
Code scanning / CodeQL
Resource exhaustion High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the problem, we need to introduce a validation step to ensure that the timeout value provided by the user is within an acceptable range. This can be done by adding a check in the invoke method of the webpage.controller.ts file to limit the timeout value before it is passed to the emit method of the event-listeners.service.ts file. Additionally, we should update the emit method to handle the validated timeout value appropriately.
| @@ -42,3 +42,3 @@ | ||
| @Transactional() | ||
| async emit<T extends EventObject>(data: T, timeout = 0): Promise<T> { | ||
| async emit<T extends EventObject>(data: T, timeout: number): Promise<T> { | ||
| // load persist listeners |
| @@ -172,3 +172,3 @@ | ||
| ), | ||
| parseInt(timeout) || 0, // sync timeout | ||
| Math.min(parseInt(timeout) || 0, 10000), // sync timeout, max 10 seconds | ||
| ); |
| const [key, order] = field.split(':'); | ||
| if (!key || !order || (allowed && !allowed.includes(key as keyof T))) | ||
| return acc; | ||
| const o = { [key]: order === 'asc' ? 'asc' : 'desc' }; |
Check failure
Code scanning / CodeQL
Remote property injection High
Pull Request Template
Description
Please include a summary of the change and which issue is fixed. Include the relevant motivation and context. List any dependencies that are required for this change.
Fixes # (issue number)
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration.
Checklist:
DCO
By submitting this pull request, I confirm that my contribution is made under the terms of the DCO 1.1 as described in CONTRIBUTING.md.
Further comments
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...