check_file_permissions(); $this->check_index_files(); $this->check_htaccess_files(); $this->check_php_files_protection(); $this->check_input_validation(); $this->check_output_escaping(); $this->check_nonce_usage(); $this->check_capability_checks(); $this->check_ssl_usage(); $this->check_rate_limiting(); return $this->generate_report(); } /** * Check file permissions */ private function check_file_permissions() { $plugin_dir = plugin_dir_path(__FILE__); // Check directory permissions (should be 755 or stricter) if (is_readable($plugin_dir)) { $perms = fileperms($plugin_dir); $octal = substr(sprintf('%o', $perms), -3); if ($octal > '755') { $this->issues[] = 'Directory permissions too permissive: ' . $octal; } else { $this->passed[] = 'Directory permissions OK: ' . $octal; } } // Check file permissions (should be 644 or stricter) $files = glob($plugin_dir . '*.php'); foreach ($files as $file) { $perms = fileperms($file); $octal = substr(sprintf('%o', $perms), -3); if ($octal > '644') { $this->issues[] = 'File permissions too permissive for ' . basename($file) . ': ' . $octal; } } if (empty($this->issues)) { $this->passed[] = 'All file permissions are secure'; } } /** * Check for index.php files in all directories */ private function check_index_files() { $plugin_dir = plugin_dir_path(__FILE__); $directories = array( $plugin_dir, $plugin_dir . 'admin/', $plugin_dir . 'includes/', $plugin_dir . 'assets/', $plugin_dir . 'assets/css/', $plugin_dir . 'assets/js/' ); foreach ($directories as $dir) { if (is_dir($dir) && !file_exists($dir . 'index.php')) { $this->issues[] = 'Missing index.php in ' . str_replace($plugin_dir, '', $dir); } else { $this->passed[] = 'index.php present in ' . str_replace($plugin_dir, '', $dir); } } } /** * Check for .htaccess files */ private function check_htaccess_files() { $plugin_dir = plugin_dir_path(__FILE__); $required_htaccess = array( $plugin_dir => 'root', $plugin_dir . 'admin/' => 'admin', $plugin_dir . 'includes/' => 'includes', $plugin_dir . 'assets/' => 'assets' ); foreach ($required_htaccess as $dir => $name) { if (file_exists($dir . '.htaccess')) { $this->passed[] = '.htaccess present in ' . $name . ' directory'; } else { $this->issues[] = 'Missing .htaccess in ' . $name . ' directory'; } } } /** * Check PHP files have direct access protection */ private function check_php_files_protection() { $plugin_dir = plugin_dir_path(__FILE__); $php_files = $this->get_all_php_files($plugin_dir); foreach ($php_files as $file) { $content = file_get_contents($file); // Skip index.php files if (basename($file) === 'index.php') { continue; } // Check for ABSPATH or WPINC checks if (!strpos($content, 'ABSPATH') && !strpos($content, 'WPINC')) { $this->issues[] = 'No direct access protection in ' . str_replace($plugin_dir, '', $file); } else { $this->passed[] = 'Direct access protected: ' . basename($file); } } } /** * Check input validation */ private function check_input_validation() { $checks = array( 'sanitize_text_field' => 'Text sanitization', 'wp_verify_nonce' => 'Nonce verification', 'esc_attr' => 'Attribute escaping', 'esc_html' => 'HTML escaping', 'esc_js' => 'JavaScript escaping', 'absint' => 'Integer validation', 'filter_var' => 'Input filtering' ); $plugin_dir = plugin_dir_path(__FILE__); $php_files = $this->get_all_php_files($plugin_dir); foreach ($checks as $function => $description) { $found = false; foreach ($php_files as $file) { $content = file_get_contents($file); if (strpos($content, $function) !== false) { $found = true; break; } } if ($found) { $this->passed[] = $description . ' implemented (' . $function . ')'; } else { $this->issues[] = $description . ' not found (' . $function . ')'; } } } /** * Check output escaping */ private function check_output_escaping() { $escaping_functions = array( 'esc_html', 'esc_attr', 'esc_url', 'esc_js', 'htmlspecialchars' ); $plugin_dir = plugin_dir_path(__FILE__); $php_files = $this->get_all_php_files($plugin_dir); $escaping_found = false; foreach ($php_files as $file) { $content = file_get_contents($file); foreach ($escaping_functions as $func) { if (strpos($content, $func) !== false) { $escaping_found = true; break 2; } } } if ($escaping_found) { $this->passed[] = 'Output escaping implemented'; } else { $this->issues[] = 'No output escaping functions found'; } } /** * Check nonce usage */ private function check_nonce_usage() { $nonce_functions = array( 'wp_create_nonce', 'wp_verify_nonce', 'wp_nonce_field', 'check_admin_referer' ); $plugin_dir = plugin_dir_path(__FILE__); $php_files = $this->get_all_php_files($plugin_dir); $nonce_found = 0; foreach ($php_files as $file) { $content = file_get_contents($file); foreach ($nonce_functions as $func) { if (strpos($content, $func) !== false) { $nonce_found++; break; } } } if ($nonce_found >= 2) { // Should have both create and verify $this->passed[] = 'Nonce protection implemented'; } else { $this->issues[] = 'Insufficient nonce protection'; } } /** * Check capability checks */ private function check_capability_checks() { $capability_functions = array( 'current_user_can', 'user_can', 'is_admin' ); $plugin_dir = plugin_dir_path(__FILE__); $php_files = $this->get_all_php_files($plugin_dir); $capability_found = false; foreach ($php_files as $file) { $content = file_get_contents($file); foreach ($capability_functions as $func) { if (strpos($content, $func) !== false) { $capability_found = true; break 2; } } } if ($capability_found) { $this->passed[] = 'Capability checks implemented'; } else { $this->issues[] = 'No capability checks found'; } } /** * Check SSL usage */ private function check_ssl_usage() { $plugin_dir = plugin_dir_path(__FILE__); $php_files = $this->get_all_php_files($plugin_dir); $https_enforced = false; foreach ($php_files as $file) { $content = file_get_contents($file); if (strpos($content, 'https://api.github.com') !== false) { $https_enforced = true; break; } } if ($https_enforced) { $this->passed[] = 'HTTPS enforced for API calls'; } else { $this->issues[] = 'HTTPS not enforced for API calls'; } } /** * Check rate limiting */ private function check_rate_limiting() { $plugin_dir = plugin_dir_path(__FILE__); $php_files = $this->get_all_php_files($plugin_dir); $rate_limiting = false; foreach ($php_files as $file) { $content = file_get_contents($file); if (strpos($content, 'rate_limit') !== false || strpos($content, 'throttl') !== false) { $rate_limiting = true; break; } } if ($rate_limiting) { $this->passed[] = 'Rate limiting implemented'; } else { $this->issues[] = 'No rate limiting found'; } } /** * Get all PHP files recursively */ private function get_all_php_files($dir) { $files = array(); $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir) ); foreach ($iterator as $file) { if ($file->isFile() && $file->getExtension() === 'php') { $files[] = $file->getPathname(); } } return $files; } /** * Generate audit report */ private function generate_report() { $report = array( 'timestamp' => current_time('mysql'), 'passed_count' => count($this->passed), 'issues_count' => count($this->issues), 'passed' => $this->passed, 'issues' => $this->issues, 'score' => $this->calculate_score(), 'status' => empty($this->issues) ? 'SECURE' : 'NEEDS ATTENTION' ); return $report; } /** * Calculate security score */ private function calculate_score() { $total = count($this->passed) + count($this->issues); if ($total === 0) { return 0; } return round((count($this->passed) / $total) * 100); } } // Run audit if requested if (isset($_GET['mcb_security_audit']) && current_user_can('manage_options')) { $audit = new MCB_Security_Audit(); $report = $audit->run_audit(); echo '
'; echo '

GitHub Code Viewer Security Audit

'; echo '
'; echo '

Security Score: ' . $report['score'] . '%

'; echo '

Status: ' . $report['status'] . '

'; echo '
'; if (!empty($report['passed'])) { echo '

✅ Passed Checks (' . $report['passed_count'] . ')

'; echo ''; } if (!empty($report['issues'])) { echo '

⚠️ Issues Found (' . $report['issues_count'] . ')

'; echo ''; } echo '

Audit completed at ' . $report['timestamp'] . '

'; echo '
'; }