mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
AAE-40427 Replace shelljs with native node api (#11404)
* Replace shelljs with native node api * Refactor command execution in audit and changelog scripts to use spawnSync for improved security and error handling
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as shell from 'shelljs';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import * as ejs from 'ejs';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
@@ -93,8 +93,45 @@ Options:
|
||||
console.log(`Running audit on ${packagePath}`);
|
||||
|
||||
const packageJson = JSON.parse(fs.readFileSync(packagePath).toString());
|
||||
const cmd = 'npm audit --json --prod';
|
||||
const jsonAudit = JSON.parse(shell.exec(cmd, { silent: true }));
|
||||
|
||||
// Run in the directory containing the package.json
|
||||
const packageDir = path.dirname(packagePath);
|
||||
|
||||
// Use spawnSync with array arguments for safer command execution (prevents shell injection)
|
||||
// Cross-platform: npm is available on PATH on all platforms (Windows, macOS, Linux)
|
||||
const result = spawnSync('npm', ['audit', '--json', '--prod'], {
|
||||
cwd: packageDir,
|
||||
encoding: 'utf-8',
|
||||
// shell: false is the default and more secure (no shell interpretation)
|
||||
shell: false,
|
||||
// Set maxBuffer to handle large audit outputs
|
||||
maxBuffer: 10 * 1024 * 1024 // 10MB
|
||||
});
|
||||
|
||||
let jsonAudit;
|
||||
|
||||
// npm audit returns non-zero exit code when vulnerabilities are found
|
||||
// We still want to parse the JSON output in this case
|
||||
if (result.error) {
|
||||
console.error('Failed to run npm audit:', result.error.message);
|
||||
reject(result.error);
|
||||
return;
|
||||
}
|
||||
|
||||
const auditOutput = result.stdout;
|
||||
if (!auditOutput) {
|
||||
console.error('npm audit produced no output');
|
||||
reject(new Error('npm audit produced no output'));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
jsonAudit = JSON.parse(auditOutput);
|
||||
} catch (parseError) {
|
||||
console.error('Failed to parse npm audit output');
|
||||
reject(parseError);
|
||||
return;
|
||||
}
|
||||
|
||||
ejs.renderFile(
|
||||
templatePath,
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
import { argv, exit } from 'node:process';
|
||||
import { parseArgs } from 'node:util';
|
||||
import * as shell from 'shelljs';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import * as path from 'path';
|
||||
import { logger } from './logger';
|
||||
import * as fs from 'fs';
|
||||
@@ -65,10 +65,22 @@ interface DiffOptions {
|
||||
* @returns URL pointing to the git remote
|
||||
*/
|
||||
function getRemote(workingDir: string): string {
|
||||
const command = 'git config --get remote.origin.url';
|
||||
const remote = shell.exec(command, { cwd: workingDir, silent: true }).toString();
|
||||
// Use spawnSync with array arguments for safer command execution (prevents shell injection)
|
||||
const result = spawnSync('git', ['config', '--get', 'remote.origin.url'], {
|
||||
cwd: workingDir,
|
||||
encoding: 'utf-8',
|
||||
shell: false
|
||||
});
|
||||
|
||||
return remote.trim();
|
||||
if (result.error) {
|
||||
throw new Error(`Failed to get git remote: ${result.error.message}`);
|
||||
}
|
||||
|
||||
if (result.status !== 0) {
|
||||
throw new Error(`git config command failed with exit code ${result.status}: ${result.stderr}`);
|
||||
}
|
||||
|
||||
return result.stdout.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,14 +99,14 @@ function getCommits(options: DiffOptions): Array<Commit> {
|
||||
authorFilter = `bot|Alfresco Build User`;
|
||||
}
|
||||
|
||||
// Build git command arguments array for safe execution (prevents shell injection)
|
||||
const args = [
|
||||
`git`,
|
||||
`log`,
|
||||
'log',
|
||||
options.range,
|
||||
`--no-merges`,
|
||||
`--first-parent`,
|
||||
'--no-merges',
|
||||
'--first-parent',
|
||||
// this format is needed to allow parsing all characters in the commit message and safely convert to JSON
|
||||
`--format="{ ^@^hash^@^: ^@^%h^@^, ^@^author^@^: ^@^%an^@^, ^@^author_email^@^: ^@^%ae^@^, ^@^date^@^: ^@^%ad^@^, ^@^subject^@^: ^@^%s^@^ }"`
|
||||
'--format={ ^@^hash^@^: ^@^%h^@^, ^@^author^@^: ^@^%an^@^, ^@^author_email^@^: ^@^%ae^@^, ^@^date^@^: ^@^%ad^@^, ^@^subject^@^: ^@^%s^@^ }'
|
||||
];
|
||||
|
||||
if (options.max !== undefined) {
|
||||
@@ -105,9 +117,23 @@ function getCommits(options: DiffOptions): Array<Commit> {
|
||||
args.push(`--skip=${options.skip}`);
|
||||
}
|
||||
|
||||
const command = args.join(' ');
|
||||
// Use spawnSync with array arguments for safer command execution
|
||||
const result = spawnSync('git', args, {
|
||||
cwd: options.dir,
|
||||
encoding: 'utf-8',
|
||||
shell: false,
|
||||
maxBuffer: 10 * 1024 * 1024 // 10MB to handle large git logs
|
||||
});
|
||||
|
||||
let log = shell.exec(command, { cwd: options.dir, silent: true }).toString();
|
||||
if (result.error) {
|
||||
throw new Error(`Failed to get git commits: ${result.error.message}`);
|
||||
}
|
||||
|
||||
if (result.status !== 0) {
|
||||
throw new Error(`git log command failed with exit code ${result.status}: ${result.stderr}`);
|
||||
}
|
||||
|
||||
let log = result.stdout;
|
||||
|
||||
// https://stackoverflow.com/a/13928240/14644447
|
||||
log = JSON.stringify(log.trim()).slice(1, -1).replace(/\^@\^/gm, '"');
|
||||
|
||||
Reference in New Issue
Block a user