fix: security and documentation fixes

- fix(utils.js): prevent command injection in commandExists() by using
  spawnSync instead of execSync with string interpolation, and validate
  input to only allow alphanumeric chars, dash, underscore, dot (#42)

- fix(utils.js): add security documentation to runCommand() warning
  against passing user-controlled input

- fix(setup-package-manager.js): replace <script> and <binary> with
  [script-name] and [binary-name] to avoid XSS scanner false positives (#43)

- fix(doc-updater.md): replace invalid 'npx ts-morph' with correct
  'npx tsx scripts/codemaps/generate.ts' since ts-morph is a library,
  not a CLI tool (#51)

Fixes #42, #43, #51
This commit is contained in:
Affaan Mustafa
2026-01-24 01:36:02 -08:00
parent a7bc5f2a90
commit 660e0d3bad
3 changed files with 22 additions and 7 deletions

View File

@@ -27,8 +27,8 @@ You are a documentation specialist focused on keeping codemaps and documentation
### Analysis Commands
```bash
# Analyze TypeScript project structure
npx ts-morph
# Analyze TypeScript project structure (run custom script using ts-morph library)
npx tsx scripts/codemaps/generate.ts
# Generate dependency graph
npx madge --image graph.svg src/

View File

@@ -223,15 +223,23 @@ function appendFile(filePath, content) {
/**
* Check if a command exists in PATH
* Uses execFileSync to prevent command injection
*/
function commandExists(cmd) {
// Validate command name - only allow alphanumeric, dash, underscore, dot
if (!/^[a-zA-Z0-9_.-]+$/.test(cmd)) {
return false;
}
try {
if (isWindows) {
execSync(`where ${cmd}`, { stdio: 'pipe' });
// Use spawnSync to avoid shell interpolation
const result = spawnSync('where', [cmd], { stdio: 'pipe' });
return result.status === 0;
} else {
execSync(`which ${cmd}`, { stdio: 'pipe' });
const result = spawnSync('which', [cmd], { stdio: 'pipe' });
return result.status === 0;
}
return true;
} catch {
return false;
}
@@ -239,6 +247,13 @@ function commandExists(cmd) {
/**
* Run a command and return output
*
* SECURITY NOTE: This function executes shell commands. Only use with
* trusted, hardcoded commands. Never pass user-controlled input directly.
* For user input, use spawnSync with argument arrays instead.
*
* @param {string} cmd - Command to execute (should be trusted/hardcoded)
* @param {object} options - execSync options
*/
function runCommand(cmd, options = {}) {
try {

View File

@@ -89,8 +89,8 @@ function detectAndShow() {
console.log('');
console.log('Commands:');
console.log(` Install: ${pm.config.installCmd}`);
console.log(` Run script: ${pm.config.runCmd} <script>`);
console.log(` Execute binary: ${pm.config.execCmd} <binary>`);
console.log(` Run script: ${pm.config.runCmd} [script-name]`);
console.log(` Execute binary: ${pm.config.execCmd} [binary-name]`);
console.log('');
}