Browse 354 rules, 42 knowledge articles, and 28 prompt templates across security, performance, architecture, and quality.
BeforeMerge scans your pull requests against these rules automatically. Get actionable feedback before code ships to production.
354 rules
Unlike PostgreSQL, MySQL/InnoDB requires indexes on foreign key columns. Missing indexes cause slow JOINs.
SELECT * fetches all columns, wasting bandwidth and preventing covering index optimization.
MySQL's utf8 charset only supports 3-byte characters. Use utf8mb4 for full Unicode support.
ALTER TABLE in MySQL can lock the entire table. Use ALGORITHM=INPLACE or tools like gh-ost for safe migrations.
Tables without primary keys cannot use logical replication and have degraded query performance.
WordPress provides context-specific escaping functions. Using the wrong one — or none — enables XSS. Match esc_html, esc_attr, esc_url, wp_kses to the output context. [CWE-79 · A07:2021]
Passing user input directly into SQL queries via $wpdb enables SQL injection. Always use $wpdb->prepare() with typed placeholders (%d, %s, %f, %i). [CWE-89 · A03:2021]
WordPress capabilities (current_user_can) are the authorization layer. Missing checks in REST endpoints, admin handlers, and AJAX allow subscribers to perform admin actions. [CWE-862 · A01:2021]
User input in include/require or file read/write paths allows attackers to read wp-config.php, delete files, or execute arbitrary PHP via ../ sequences. [CWE-22 · A01:2021]
PHP's unserialize() instantiates arbitrary classes and triggers magic methods. Deserialization of user input enables remote code execution via gadget chains. [CWE-502 · A08:2021]
Direct move_uploaded_file() with only client-supplied MIME checks enables shell upload. Use wp_handle_upload() which validates both extension and file content. [CWE-434 · A04:2021]
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]
WordPress nonces prevent CSRF attacks. Every form submission, AJAX call, and admin action that modifies data must verify a nonce before processing. [CWE-352 · A01:2021]
WordPress AJAX handlers are public endpoints. wp_ajax_ fires for any logged-in user regardless of role. Always verify nonces and capabilities inside each handler. [CWE-862 · A01:2021]
Returning false on failure hides what went wrong. WP_Error provides structured error codes, messages, and data — matching WordPress core's error handling pattern.
Raw $_GET/$_POST/$_REQUEST data can contain anything. WordPress provides type-specific sanitization functions — use the right one for each data type before storage or use. [CWE-20 · A03:2021]
Hardcoded English strings prevent localization. Use __(), _e(), and esc_html__() with a text domain. Always escape translated output — translators can inject HTML.
External API calls, complex calculations, and aggregation queries should use set_transient/get_transient to avoid repeating expensive work on every page load.
Direct $wpdb queries and query_posts() in template files create redundant queries, bypass caching, and mix data logic with presentation.
Inline script tags bypass WordPress dependency management and load on every page. Use wp_enqueue_script with conditions to load assets only where needed.
wp_cache_get/set with a persistent backend (Redis/Memcached) eliminates redundant database queries across requests. Without it, identical queries run on every page load.
Calling get_post_meta() inside loops without cache priming generates one database query per post. Use update_post_meta_cache or meta_query to batch lookups.
All autoloaded options are loaded into memory on every page request. Large serialized arrays in autoloaded options waste memory and slow every page.
Direct SQL, curl, file_put_contents, and mail() bypass WordPress caching, hooks, security filters, and host compatibility. Use WP_Query, wp_remote_get, WP_Filesystem, and wp_mail.