Guard Plugin and Theme PHP Files Against Direct Access
Share
PHP files without an ABSPATH guard can be accessed directly via URL, leaking paths, triggering errors, or executing partial logic without WordPress security context. [CWE-425 · A05:2021]
Why This Matters
prevents information disclosure and unguarded code execution from direct file requests
Guard Plugin and Theme PHP Files Against Direct Access
Impact: HIGH (prevents information disclosure and unguarded code execution from direct file requests)
Every PHP file in a WordPress plugin or theme is directly accessible via URL unless protected. When accessed directly (e.g., https://example.com/wp-content/plugins/my-plugin/includes/process.php), the file executes without the WordPress bootstrap — no security checks, no authentication, no API functions loaded. This can:
Reveal server paths and PHP versions in error messages
Execute partial logic without nonce or capability verification
Expose debug output or database credentials
Allow direct invocation of file operations
Incorrect (no access guard):
<?php// wp-content/plugins/my-plugin/includes/helpers.php// ❌ No guard — directly accessible via URLfunction process_data( $input ) { global $wpdb; // Fatal error: $wpdb is null when accessed directly // Error message leaks server path and WordPress install location return $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}posts" );}
<?php// ❌ File with initialization logic that runs on include// Direct access triggers this without WordPress context$config = include __DIR__ . '/config.php'; // May expose sensitive values$db = new PDO( $config['dsn'] ); // Direct DB connection without WP safeguards
Correct (ABSPATH guard at the top of every file):
<?php// ✅ First executable line in every plugin/theme PHP fileif ( ! defined( 'ABSPATH' ) ) { exit;}function process_data( $input ) { global $wpdb; return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}posts WHERE post_status = %s", 'publish' ) );}
Template files, class files, include files, helper files
Exception: The main plugin file (the one with the Plugin Name: header) — WordPress loads this directly, so it should define its own constant or check ABSPATH early