/** * Options for safe command execution */ export interface SafeExecOptions { /** Character encoding for output (default: undefined = Buffer) */ encoding?: BufferEncoding; /** Standard I/O configuration */ stdio?: 'pipe' | 'ignore' | 'inherit' | Array<'pipe' | 'ignore' | 'inherit'>; /** Environment variables (merged with process.env if not fully specified) */ env?: NodeJS.ProcessEnv; /** Working directory */ cwd?: string; /** Maximum output buffer size in bytes */ maxBuffer?: number; /** Timeout in milliseconds */ timeout?: number; } /** * Result of a safe command execution */ export interface SafeExecResult { /** Whether the command exited successfully (status === 0) */ success: boolean; /** Exit code (0 = success) */ status: number; /** Standard output */ stdout: Buffer | string; /** Standard error */ stderr: Buffer | string; /** Error object if command failed to spawn */ error?: Error; } /** * Error thrown when command execution fails */ export declare class CommandExecutionError extends Error { readonly status: number; readonly stdout: Buffer | string; readonly stderr: Buffer | string; constructor(message: string, status: number, stdout: Buffer | string, stderr: Buffer | string); } /** * Safe command execution using spawnSync + which pattern * * More secure than execSync: * - Resolves PATH once using pure Node.js (which package) * - Executes with absolute path and shell: false * - No shell interpreter = no command injection risk * - Supports custom env vars (e.g., GIT_INDEX_FILE) * * @param command - Command name (e.g., 'git', 'gitleaks', 'node') * @param args - Array of arguments * @param options - Execution options * @returns Buffer or string output * @throws Error if command not found or execution fails * * @example * // Tool detection * safeExecSync('gitleaks', ['--version'], { stdio: 'ignore' }); * * @example * // Git with custom env * safeExecSync('git', ['add', '--all'], { * env: { ...process.env, GIT_INDEX_FILE: tempFile } * }); * * @example * // Get output as string * const version = safeExecSync('node', ['--version'], { encoding: 'utf8' }); */ export declare function safeExecSync(command: string, args?: string[], options?: SafeExecOptions): Buffer | string; /** * Safe command execution that returns detailed result (doesn't throw) * * Use this when you need to handle errors programmatically * instead of catching exceptions. * * @param command - Command name (e.g., 'git', 'node') * @param args - Array of arguments * @param options - Execution options * @returns Detailed execution result * * @example * const result = safeExecResult('git', ['status']); * if (result.success) { * console.log(result.stdout.toString()); * } else { * console.error(`Failed: ${result.stderr.toString()}`); * } */ export declare function safeExecResult(command: string, args?: string[], options?: SafeExecOptions): SafeExecResult; /** * Check if a command-line tool is available * * @param toolName - Name of tool to check (e.g., 'gh', 'gitleaks', 'node') * @returns true if tool is available, false otherwise * * @example * if (isToolAvailable('gh')) { * console.log('GitHub CLI is installed'); * } */ export declare function isToolAvailable(toolName: string): boolean; /** * Get tool version if available * * @param toolName - Name of tool (e.g., 'node', 'pnpm') * @param versionArg - Argument to get version (default: '--version') * @returns Version string or null if not available * * @example * const nodeVersion = getToolVersion('node'); * console.log(nodeVersion); // "v20.11.0" * * @example * const gitVersion = getToolVersion('git', 'version'); * console.log(gitVersion); // "git version 2.39.2" */ export declare function getToolVersion(toolName: string, versionArg?: string): string | null; /** * Check if a command string contains shell-specific syntax * * Detects patterns that require shell interpretation: * - Quotes (", ', `) * - Glob patterns (*, ?, []) * - Variable expansion ($) * - Pipes/redirects/operators (|, >, <, &, ;, &&, ||) * * Performance: Single-pass O(n) algorithm with O(1) Set lookups. * Short-circuits on first match (no backtracking, no regex overhead). * * @param commandString - Command string to check * @returns Object with detection result and details * * @example * ```typescript * const check1 = hasShellSyntax('npm test'); * console.log(check1); // { hasShellSyntax: false } * * const check2 = hasShellSyntax('npm test && npm run build'); * console.log(check2); * // { * // hasShellSyntax: true, * // pattern: 'pipes/redirects/operators', * // example: 'cat file | grep text' * // } * ``` */ export declare function hasShellSyntax(commandString: string): { hasShellSyntax: boolean; pattern?: string; example?: string; }; /** * Execute a command from a simple command string (convenience wrapper) * * **IMPORTANT: Shift-Left Validation** - This function actively rejects shell syntax * to prevent subtle bugs where shell features are expected but not executed. * * **Supported:** * - Simple commands: `git status`, `pnpm test`, `node --version` * - Commands with flags: `git log --oneline --max-count 10` * - Multiple unquoted arguments: `gh pr view 123` * * **NOT Supported (will throw error):** * - Quotes: `echo "hello world"` ❌ * - Glob patterns: `ls *.txt` ❌ * - Variable expansion: `echo $HOME` ❌ * - Pipes/redirects: `cat file | grep text` ❌ * - Command chaining: `build && test` ❌ * * **Why these restrictions?** * We don't use a shell interpreter (for security), so shell features like * glob expansion, variable substitution, and pipes don't work. By detecting * and rejecting these patterns, we force you to use the safer `safeExecSync()` * API with explicit argument arrays. * * @param commandString - Simple command string (no shell syntax) * @param options - Execution options * @returns Command output (Buffer or string depending on encoding option) * @throws Error if command contains shell-specific syntax * * @example * ```typescript * // ✅ Simple commands (these work) * safeExecFromString('git status'); * safeExecFromString('pnpm test --watch'); * safeExecFromString('gh pr view 123'); * ``` * * @example * ```typescript * // ❌ Shell syntax (these throw errors) * safeExecFromString('echo "hello"'); // Quotes * safeExecFromString('ls *.txt'); // Glob pattern * safeExecFromString('cat file | grep text'); // Pipe * safeExecFromString('echo $HOME'); // Variable expansion * * // ✅ Use safeExecSync() instead with explicit arguments * safeExecSync('echo', ['hello']); * safeExecSync('ls', ['file1.txt', 'file2.txt']); // Or use glob library * safeExecSync('grep', ['text', 'file']); * safeExecSync('echo', [process.env.HOME || '']); * ``` * */ export declare function safeExecFromString(commandString: string, options?: SafeExecOptions): Buffer | string; //# sourceMappingURL=safe-exec.d.ts.map