diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 000000000..b1d2347f3 --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,7 @@ +paths: + - "src" +paths-ignore: + - "src/__tests__/**/*.js" + - "src/__tests__/**/*.ts" + - "src/__tests__/**/*.jsx" + - "src/__tests__/**/*.tsx" diff --git a/src/__tests__/if-check/util/npm.test.ts b/src/__tests__/if-check/util/npm.test.ts index 6363ddf32..816dcc715 100644 --- a/src/__tests__/if-check/util/npm.test.ts +++ b/src/__tests__/if-check/util/npm.test.ts @@ -25,7 +25,7 @@ jest.mock('../../../common/util/helpers', () => { break; case 'if-check': expect(param).toEqual( - "npm run if-env -- -m ./src/__mocks__/mock-manifest.yaml && npm run if-run -- -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest && node -p 'Boolean(process.stdout.isTTY)' | npm run if-diff -- -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml" + "npm run if-env -- -m ./src/__mocks__/mock-manifest.yaml && npm run if-run -- -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest && node -p 'Boolean(process.stdout.isTTY)' | npm run if-diff -- -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml" ); break; case 'if-check-cwd': diff --git a/src/if-check/util/npm.ts b/src/if-check/util/npm.ts index a6137a9d3..9717819f3 100644 --- a/src/if-check/util/npm.ts +++ b/src/if-check/util/npm.ts @@ -1,43 +1,75 @@ import * as path from 'node:path'; - import {execPromise} from '../../common/util/helpers'; import {getFileName, removeFileIfExists} from '../../common/util/fs'; - import {STRINGS} from '../config'; const {IF_CHECK_VERIFIED} = STRINGS; +/** + * Escapes shell characters that could be dangerous in a command. + */ +const escapeShellArg = (str: string) => str.replace(/([`$\\&;|*?<>])/g, '\\$1'); + /** * Executes a series of npm commands based on the provided manifest file. */ export const executeCommands = async (manifest: string, cwd: boolean) => { - // TODO: After release remove isGlobal and appropriate checks const isGlobal = !!process.env.npm_config_global; const manifestDirPath = path.dirname(manifest); const manifestFileName = getFileName(manifest); const executedManifest = path.join(manifestDirPath, `re-${manifestFileName}`); + const prefixFlag = process.env.CURRENT_DIR && process.env.CURRENT_DIR !== process.cwd() ? `--prefix=${path.relative(process.env.CURRENT_DIR!, process.cwd())}` : ''; - const ifEnv = `${ - isGlobal ? `if-env ${prefixFlag}` : `npm run if-env ${prefixFlag} --` - } -m ${manifest}`; - const ifEnvCommand = cwd ? `${ifEnv} -c` : ifEnv; - const ifRunCommand = `${ - isGlobal ? `if-run ${prefixFlag}` : `npm run if-run ${prefixFlag} --` - } -m ${manifest} -o ${executedManifest}`; - const ifDiffCommand = `${ - isGlobal ? `if-diff ${prefixFlag}` : `npm run if-diff ${prefixFlag} --` - } -s ${executedManifest}.yaml -t ${manifest}`; - const ttyCommand = " node -p 'Boolean(process.stdout.isTTY)'"; - - await execPromise( - `${ifEnvCommand} && ${ifRunCommand} && ${ttyCommand} | ${ifDiffCommand}`, - { - cwd: process.env.CURRENT_DIR || process.cwd(), - } - ); + + const sanitizedManifest = escapeShellArg(manifest); + const sanitizedExecutedManifest = escapeShellArg(executedManifest); + + const ifEnvCommand = [ + isGlobal ? 'if-env' : 'npm run if-env', + '--', + ...(prefixFlag === '' ? [] : prefixFlag), + '-m', + sanitizedManifest, + ]; + + const ifRunCommand = [ + isGlobal ? 'if-run' : 'npm run if-run', + '--', + ...(prefixFlag === '' ? [] : prefixFlag), + '-m', + sanitizedManifest, + '-o', + sanitizedExecutedManifest, + ]; + + const ttyCommand = ['node', '-p', "'Boolean(process.stdout.isTTY)'"]; + const ifDiffCommand = [ + isGlobal ? 'if-diff' : 'npm run if-diff', + '--', + ...(prefixFlag === '' ? [] : prefixFlag), + '-s', + `${sanitizedExecutedManifest}.yaml`, + '-t', + sanitizedManifest, + ]; + + const fullCommand = [ + ...ifEnvCommand, + '&&', + ...ifRunCommand, + '&&', + ...ttyCommand, + '|', + ...ifDiffCommand, + ].join(' '); + + // Execute the full command + await execPromise(fullCommand, { + cwd: process.env.CURRENT_DIR || process.cwd(), + }); if (!cwd) { await removeFileIfExists(`${manifestDirPath}/package.json`);