|
7 | 7 |
|
8 | 8 | import { homedir, tmpdir } from 'os'; |
9 | 9 | import { join } from 'path'; |
10 | | -import { execSync } from 'child_process'; |
| 10 | +import { execSync, execFileSync } from 'child_process'; |
11 | 11 |
|
12 | 12 | /** |
13 | 13 | * Expand template variables in strings |
@@ -169,8 +169,12 @@ export interface QsvValidationResult { |
169 | 169 | */ |
170 | 170 | function detectQsvBinaryPath(): string | null { |
171 | 171 | try { |
172 | | - const command = process.platform === 'win32' ? 'where qsv' : 'which qsv'; |
173 | | - const result = execSync(command, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }); |
| 172 | + // Use execFileSync instead of execSync for security best practice |
| 173 | + const command = process.platform === 'win32' ? 'where' : 'which'; |
| 174 | + const result = execFileSync(command, ['qsv'], { |
| 175 | + encoding: 'utf8', |
| 176 | + stdio: ['ignore', 'pipe', 'ignore'] |
| 177 | + }); |
174 | 178 | const path = result.trim().split('\n')[0]; // Take first result |
175 | 179 | return path || null; |
176 | 180 | } catch { |
@@ -210,7 +214,8 @@ function compareVersions(v1: string, v2: string): number { |
210 | 214 | */ |
211 | 215 | export function validateQsvBinary(binPath: string): QsvValidationResult { |
212 | 216 | try { |
213 | | - const result = execSync(`"${binPath}" --version`, { |
| 217 | + // Use execFileSync instead of execSync to prevent command injection |
| 218 | + const result = execFileSync(binPath, ['--version'], { |
214 | 219 | encoding: 'utf8', |
215 | 220 | stdio: ['ignore', 'pipe', 'pipe'], |
216 | 221 | timeout: 5000 // 5 second timeout |
|
0 commit comments