$sanitized_line) { if (preg_match('/\bproc_open\s*\(/i', $sanitized_line)) { $line_number = $line_num + 1; $original_line = $original_lines[$line_num] ?? $sanitized_line; $this->add_violation( $file_path, $line_number, $this->get_violation_message(), trim($original_line), $this->get_resolution_message(), 'critical' ); return; // Only report first occurrence } } } private function get_violation_message(): string { return "🚨 CRITICAL: proc_open() is BANNED in this codebase After 10+ attempts to fix pipe buffer truncation bugs, proc_open() is now completely banned. WHY THIS IS BANNED: - Unfixable race conditions with feof() cause silent data loss on large outputs (35KB+) - Even 'correct' patterns using while (!feof(\$pipes[...])) still have race conditions - We never need asynchronous operations - all our use cases are synchronous REAL-WORLD INCIDENTS: 1. JqhtmlWebpackCompiler.php - Compiled template truncated at 8KB, breaking JavaScript 2. Multiple attempts to fix with different buffering strategies all failed 3. Pattern matches known PHP bug reports going back years THE FUNDAMENTAL PROBLEM: - Child process writes to pipe - Parent checks feof() but pipe hasn't been marked EOF yet - fread() returns empty string - Loop continues, feof() now returns true prematurely - Remaining data silently lost This is NOT a coding error - it's a race condition in proc_open() itself."; } private function get_resolution_message(): string { return "REQUIRED ACTION - Replace proc_open() with one of these RELIABLE alternatives: OPTION 1: File Redirection (RECOMMENDED for large outputs) // Redirect output to temp file - filesystem is reliable, pipes are not \$temp_file = storage_path('rsx-tmp/output_' . uniqid() . '.txt'); \$command = sprintf( '%s > %s 2>&1', escapeshellarg(\$your_command), escapeshellarg(\$temp_file) ); exec(\$command, \$output_lines, \$return_code); // Read complete output from file if (file_exists(\$temp_file)) { \$output = file_get_contents(\$temp_file); unlink(\$temp_file); // Clean up } WHY THIS WORKS: - OS guarantees file writes are complete before exec() returns - No pipes, no race conditions, no truncation - How webpack, rollup, and other build tools handle large outputs - Simple, reliable, debuggable OPTION 2: shell_exec() (for smaller outputs < 1MB) \$output = shell_exec(\$command . ' 2>&1'); if (\$output === null) { throw new RuntimeException('Command execution failed'); } WHY THIS WORKS: - PHP's shell_exec() uses different buffering mechanism - No manual pipe handling, no feof() race conditions - Specifically designed for capturing full command output OPTION 3: exec() with output array (line-oriented output) exec(\$command, \$output_lines, \$return_code); \$output = implode(\"\\n\", \$output_lines); WHY THIS WORKS: - Reliable for line-oriented output - No pipe buffer issues - Simpler than proc_open() DO NOT attempt to 'fix' proc_open() with better buffering strategies. We've tried that 10+ times. It doesn't work. Use the alternatives above."; } }