From 4aae6bae1ccf8d917556b919dfa1cc5d817a649a Mon Sep 17 00:00:00 2001 From: Zeroday BYTE Date: Tue, 3 Jun 2025 16:35:31 +0700 Subject: [PATCH] fix(packages): shell command built from environment values (#12386) https://github.com/twentyhq/twenty/blob/b7473371b3fda51de96241533dc7d56856134f72/packages/twenty-server/src/engine/core-modules/serverless/commands/add-packages.command.ts#L6-L6 https://github.com/twentyhq/twenty/blob/b7473371b3fda51de96241533dc7d56856134f72/packages/twenty-server/src/engine/core-modules/serverless/commands/add-packages.command.ts#L10-L10 https://github.com/twentyhq/twenty/blob/b7473371b3fda51de96241533dc7d56856134f72/packages/twenty-server/src/engine/core-modules/serverless/commands/add-packages.command.ts#L79-L79 Fix the issue should avoid dynamically constructing the shell command. Instead, we can use `execFile` or `execFileSync`, which allows us to pass arguments as an array, avoiding shell interpretation of special characters. This ensures that the `folderPath` is treated as a literal argument and not subject to command injection. Specifically: 1. Replace the use of `execPromise` with `execFilePromise` (a promisified version of `execFile`). 2. Modify the `addToGit` method to pass the `folderPath` as an argument to `git add` instead of interpolating it into the command string. --- --- .../serverless/commands/add-packages.command.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/twenty-server/src/engine/core-modules/serverless/commands/add-packages.command.ts b/packages/twenty-server/src/engine/core-modules/serverless/commands/add-packages.command.ts index 227602944..c57bc8a48 100644 --- a/packages/twenty-server/src/engine/core-modules/serverless/commands/add-packages.command.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/commands/add-packages.command.ts @@ -1,13 +1,13 @@ import { Logger } from '@nestjs/common'; +import { execFile } from 'child_process'; import * as fs from 'fs/promises'; import { resolve } from 'path'; import { promisify } from 'util'; -import { exec } from 'child_process'; import { Command, CommandRunner, Option } from 'nest-commander'; -const execPromise = promisify(exec); +const execFilePromise = promisify(execFile); @Command({ name: 'serverless:add-packages', @@ -40,7 +40,6 @@ export class AddPackagesCommand extends CommandRunner { ); const currentVersion = await this.getLastLayerVersion(); - const newVersion = currentVersion + 1; const currentVersionFolder = `${layersFolder}/${currentVersion}`; @@ -71,12 +70,11 @@ export class AddPackagesCommand extends CommandRunner { private getAbsoluteFilePath(path: string) { const rootPath = process.cwd(); - return resolve(rootPath, path); } private async addToGit(folderPath: string) { - await execPromise(`git add ${folderPath}`); + await execFilePromise('git', ['add', folderPath]); } private async cleanPackageInstallation(folderPath: string) { @@ -95,7 +93,7 @@ export class AddPackagesCommand extends CommandRunner { for (const packageName of packages) { this.logger.log(`- adding '${packageName}'...`); try { - await execPromise(`yarn add ${packageName}`, { + await execFilePromise('yarn', ['add', packageName], { cwd: folderPath, }); } catch (error) {