diff --git a/bin/aios-init.js b/bin/aios-init.js index c9cbe98c3..1868a91e8 100644 --- a/bin/aios-init.js +++ b/bin/aios-init.js @@ -36,14 +36,15 @@ const execAsync = promisify(exec); /** * Execute command with inherited stdio (for npm install -g that needs user interaction) * INS-2 Performance: Async version that doesn't block event loop - * @param {string} command - Command to execute + * Security: Uses array args without shell interpretation + * @param {string} program - Program to execute + * @param {string[]} args - Arguments array * @param {object} options - Spawn options * @returns {Promise} */ -function spawnAsync(command, options = {}) { +function spawnAsync(program, args = [], options = {}) { return new Promise((resolve, reject) => { - const [cmd, ...args] = command.split(' '); - const child = spawn(cmd, args, { stdio: 'inherit', shell: true, ...options }); + const child = spawn(program, args, { stdio: 'inherit', ...options }); child.on('close', (code) => { if (code === 0) { resolve(); @@ -480,7 +481,7 @@ async function main() { console.log(chalk.blue(`📥 Installing ${tool.name}...`)); try { // INS-2 Performance: Use async spawn instead of sync (AC7) - await spawnAsync(`npm install -g ${tool.npm}`); + await spawnAsync('npm', ['install', '-g', tool.npm]); console.log(chalk.green('✓') + ` ${tool.name} installed successfully`); // Show post-install instructions diff --git a/bin/aios.js b/bin/aios.js index d57951b60..c5c4920b1 100755 --- a/bin/aios.js +++ b/bin/aios.js @@ -475,7 +475,8 @@ Examples: fixAction: async () => { console.log(' 🔧 Installing AIOS...'); try { - execSync('npx aios-core install --force --quiet', { stdio: 'inherit', timeout: 60000 }); + // Use local wizard instead of npx to avoid supply chain risk + await runWizard({ force: true, quiet: true }); console.log(' ✓ Installation complete'); } catch (installError) { console.error(` ✗ Installation failed: ${installError.message}`);