Table of Contents
- The State of wp.org Submissions in 2026
- Why Plugins Get Rejected
- Security Issues: The Top Rejection Category
- Code Quality and Standards Failures
- Common Misunderstandings About Review
- How to Respond to Reviewer Feedback
- Prevention Strategies Before Submission
- Tools That Help Catch Issues Early
- Frequently Asked Questions
The State of wp.org Submissions in 2026
WordPress.org plugin directory submissions have exploded. With over 65,000 plugins already approved and thousands of new submissions each month, the review process has become increasingly stringent. The current rejection rate sits at approximately 30.5%—meaning nearly one in three plugins fails on first submission.
Before submitting, run your plugin through WP HealthKit's free audit to catch these issues automatically.
This isn't arbitrary gatekeeping. The WordPress security team and volunteer reviewers are protecting millions of website owners. A single vulnerable plugin can compromise thousands of installations. The stakes are high, and the standards reflect that reality.
What's changed since 2025? Reviewers now focus harder on automated security checks, accessibility compliance, and proper use of WordPress APIs. Many developers still treat these as optional niceties. They're not. They're prerequisites.
If your plugin was rejected, you're not alone. Most rejections fall into predictable categories—and most are preventable with the right knowledge and tools.
Why Plugins Get Rejected
Rejection typically falls into three buckets: security vulnerabilities, poor code quality, and architectural problems. Let me break down the specific reasons reviewers send rejections back to developers.
The most common rejections cite missing security practices. That includes unescaped output, missing nonces, inadequate sanitization, and direct file access vulnerabilities. These aren't edge cases or theoretical risks. Reviewers have seen real exploits in the wild.
The second wave covers WordPress coding standards. Proper use of hooks, correct filter application, avoiding direct database queries when APIs exist—these represent the difference between a plugin that plays nicely in the WordPress ecosystem and one that breaks other plugins or themes.
Third comes functionality and user experience. Does the plugin provide real value? Is the code maintainable? Are there obvious performance red flags? Does it respect user data?
Understanding which category your rejection falls into matters. The fixes differ dramatically between security and styling issues.
Security Issues: The Top Rejection Category
Security violations account for roughly 45% of all rejections. These are the show-stoppers—reviewers will not approve plugins with unpatched security holes.
1. Unescaped Output (XSS Vulnerability)
The most flagged issue: developers output data without escaping. This opens cross-site scripting (XSS) vulnerabilities that attackers exploit.
Bad code:
<?php
echo $user_input; // Directly echoing user data
?>
An attacker submits JavaScript in a form field, and it executes in browsers. Game over.
Correct fix:
<?php
echo esc_html( $user_input );
?>
The esc_html() function converts dangerous characters to HTML entities. If you're outputting HTML attributes, use esc_attr(). For JavaScript contexts, esc_js(). The rule is simple: always escape based on context.
WP HealthKit check: The "Output Escaping Audit" flag detects unescaped echo statements and suggests the appropriate escaping function.
2. Missing Nonces (CSRF Vulnerability)
Forms that modify data require nonces—cryptographic tokens that verify requests came from your legitimate user, not an attacker's malicious site.
Bad code:
<?php
if ( isset( $_POST['save_settings'] ) ) {
update_option( 'my_setting', sanitize_text_field( $_POST['value'] ) );
}
?>
Without a nonce, an attacker can trick a logged-in user into submitting this form from anywhere. The settings get changed without the user knowing.
Correct fix:
<?php
// In your form:
wp_nonce_field( 'save_my_settings_nonce' );
// In your handler:
if ( isset( $_POST['save_settings'] ) ) {
check_admin_referer( 'save_my_settings_nonce' );
update_option( 'my_setting', sanitize_text_field( $_POST['value'] ) );
}
?>
Every form that modifies database state must include a nonce. This is non-negotiable for approval.
WP HealthKit check: The "Form Security Audit" identifies missing nonces on POST handlers and missing referer checks.
3. Inadequate Input Sanitization
Sanitizing data before storing it prevents injection attacks and data corruption.
Bad code:
<?php
$user_data = $_POST['user_email'];
$wpdb->insert( 'wp_users', array( 'email' => $user_data ) );
?>
If that email contains SQL injection syntax, the database query breaks or exposes data.
Correct fix:
<?php
$user_data = sanitize_email( $_POST['user_email'] );
$wpdb->insert( 'wp_users', array( 'email' => $user_data ), array( '%s' ) );
?>
Use context-specific sanitization: sanitize_email(), sanitize_text_field(), sanitize_key() for option names, and prepared statements for all database queries.
WP HealthKit check: The "Input Sanitization Audit" detects $_POST, $_GET, and $_REQUEST usage without sanitization, flagging the specific variable and suggesting appropriate functions.
4. Direct Database Queries When APIs Exist
Developers often bypass WordPress APIs and query the database directly. This creates maintenance nightmares and security risks.
Bad code:
<?php
global $wpdb;
$result = $wpdb->get_results( "SELECT * FROM {$wpdb->posts} WHERE post_type = 'post'" );
?>
This query breaks if WordPress changes the schema. It doesn't respect post statuses, custom fields, or metadata. It's unmaintainable.
Correct fix:
<?php
$posts = get_posts( array(
'post_type' => 'post',
'numberposts' => -1,
) );
?>
WordPress provides get_posts(), get_users(), get_terms(), and dozens of other functions that handle complex logic for you. Use them.
WP HealthKit check: The "API Usage Audit" identifies direct $wpdb queries and recommends the proper WordPress API alternative.
5. No Capability Checks Before Admin Actions
Any code that performs admin actions must verify the user has permission.
Bad code:
<?php
if ( isset( $_POST['delete_all_posts'] ) ) {
$wpdb->query( "DELETE FROM {$wpdb->posts}" );
}
?>
Any user—even a subscriber—could trigger post deletion.
Correct fix:
<?php
if ( isset( $_POST['delete_all_posts'] ) ) {
if ( ! current_user_can( 'delete_posts' ) ) {
wp_die( 'Unauthorized' );
}
check_admin_referer( 'delete_posts_nonce' );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->posts} WHERE post_type = %s", 'post' ) );
}
?>
Always verify current_user_can() before sensitive operations. Combine this with nonces.
WP HealthKit check: The "Capability Audit" identifies admin-facing actions without capability checks and reports the missing verification.
Code Quality and Standards Failures
Security is foundational, but reviewers also enforce coding standards that keep the ecosystem healthy.
6. Improper Hook Usage
WordPress provides hooks for extending functionality—but many developers use them incorrectly, breaking proper inheritance.
Bad code:
<?php
function my_filter_callback( $content ) {
return $content . ' - modified';
}
// Wrong hook—too late, changes aren't applied everywhere
add_filter( 'the_content', 'my_filter_callback', 999 );
?>
The priority 999 (very late execution) means other plugins' modifications get lost. Filters applied at the wrong point in the lifecycle don't work as expected.
Correct fix:
<?php
function my_filter_callback( $content ) {
return $content . ' - modified';
}
// Default priority (10) at the right lifecycle point
add_filter( 'the_content', 'my_filter_callback' );
?>
Use default priority unless you have a specific reason otherwise. Apply filters at the right lifecycle hooks. Run do_action() only at logical extension points.
WP HealthKit check: The "Hook Standards Audit" detects unusual priority numbers and suggests reviewing the hook's purpose.
7. Missing Text Domains for Translation
WordPress supports multiple languages. Strings must be wrapped in translation functions.
Bad code:
<?php
echo "Settings saved successfully";
?>
Translators can't find this string. International users see English only.
Correct fix:
<?php
echo esc_html__( "Settings saved successfully", 'my-plugin' );
?>
Wrap every user-facing string in esc_html__(), esc_attr__(), or __() with your plugin's text domain. Load the text domain in a function hooked to plugins_loaded.
WP HealthKit check: The "i18n Audit" identifies hardcoded strings and suggests wrapping them in the appropriate translation function.
8. Deprecated Function Usage
WordPress deprecates functions when better alternatives exist. Using deprecated functions creates maintenance debt.
Bad code:
<?php
$users = get_userdatabylogin( 'john' ); // Deprecated since 3.0!
?>
This function is slow, unmaintained, and will eventually disappear.
Correct fix:
<?php
$user = get_user_by( 'login', 'john' );
?>
Modern WordPress provides purpose-built functions. Reviewers reject plugins using long-deprecated functions—it signals careless code.
WP HealthKit check: The "Deprecation Audit" identifies deprecated function calls and shows the recommended replacement.
9. No Uninstall Cleanup
When users delete a plugin, temporary data should be cleaned up. Missing cleanup leaves database cruft.
Bad code:
<?php
// Plugin adds options and posts but never removes them
register_activation_hook( __FILE__, function() {
add_option( 'my_plugin_setting', 'default' );
} );
?>
When uninstalled, all that data stays in the database forever.
Correct fix:
<?php
register_activation_hook( __FILE__, function() {
add_option( 'my_plugin_setting', 'default' );
} );
register_uninstall_hook( __FILE__, function() {
delete_option( 'my_plugin_setting' );
} );
?>
Implement proper cleanup. Create an uninstall.php file or use register_uninstall_hook() to remove all plugin data.
WP HealthKit check: The "Cleanup Audit" detects plugins that create options, custom post types, or custom tables without corresponding uninstall routines.
10. Missing README.txt or Invalid Headers
Metadata about your plugin must be complete and accurate.
Bad code:
=== My Awesome Plugin ===
Contributors: me
Version: 1
Missing required headers, unclear description, no installation instructions.
Correct fix:
=== My Awesome Plugin ===
Contributors: me
Version: 1.0.0
Requires at least: 5.0
Tested up to: 6.7
License: GPL v2 or later
Description: Provides advanced user analytics with real-time dashboard.
Installation: 1. Upload to /wp-content/plugins/ 2. Activate 3. Visit Settings > My Plugin
Include version numbers, WordPress requirements, tested-up-to version, license, clear description, and installation instructions.
WP HealthKit check: The "Metadata Audit" validates README.txt headers against official requirements.
Common Misunderstandings About Review
Many rejected developers assumed their code was fine. Let me clarify what reviewers actually check.
Myth: "My code works, so it's ready."
Working code is the baseline. Reviewers audit security, standards compliance, and maintenance. Working code that exposes user data to XSS attacks still gets rejected.
Myth: "Small plugins don't need security practices."
Scale doesn't matter. A plugin with 10 users still needs nonces, escaping, and sanitization. Security standards apply universally.
Myth: "Reviewers only care about security."
False. They check security first, then code quality, then functionality. A secure plugin with abysmal code practices can still be rejected. They want code other developers can maintain.
Myth: "I can't resubmit the same plugin quickly."
You can resubmit immediately after fixing issues. Reviewers expect rapid turnarounds. Submit a fix, resubmit, and get reviewed again within 1-2 days typically.
Myth: "If it passes automated tools, it will pass review."
Automated tools catch obvious issues. Human reviewers catch logic errors, architectural problems, and edge cases. Tools are necessary but insufficient.
How to Respond to Reviewer Feedback
When you receive a rejection, reviewers provide specific guidance. How you respond determines your path to approval.
First, read the entire rejection message carefully. Reviewers cite specific lines and explain the violation. They're not being difficult—they're telling you exactly what to fix.
Create a detailed response addressing each point. Show that you understand the issue and have implemented the proper fix. Paste the corrected code in the resubmission message.
If you disagree with feedback, ask for clarification rather than arguing. Reviewers have seen thousands of plugins. Their experience is valuable even when you don't immediately understand their concern.
Common response structures that work:
Good response: "Thank you for the feedback. I've addressed the missing nonce on line 145 by adding wp_nonce_field() to the form and check_admin_referer() to the handler. I've also wrapped all output on lines 67-72 with esc_html(). Please see the updated code below."
Poor response: "I don't think this is a real security issue. My users are trusted."
The second response guarantees another rejection. Reviewers are protecting installations from any user, trusted or not. Frame responses as learning and improvement, not defense.
Prevention Strategies Before Submission
The best rejection to handle is the one you prevent. Run audits before submitting.
Step 1: Use WordPress Coding Standards
Install PHP CodeSniffer with WordPress-specific rules:
composer require squizlabs/php_codesniffer --dev
composer require wp-coding-standards/wpcs --dev
phpcs --standard=WordPress your-plugin-file.php
This catches improper function names, deprecated usage, missing documentation, and style violations automatically.
Step 2: Check for Common Vulnerabilities
Review your code manually for the ten issues outlined above. Create a checklist:
- Every form includes a nonce
- Every
$_POST/$_GETis sanitized - Every output is escaped
- No direct database queries (use APIs instead)
- Every admin action checks capabilities
- No deprecated function calls
- All strings use translation functions
- Proper cleanup on uninstall
- All hooks used correctly
- README.txt headers are complete
Step 3: Run Plugin Check Locally
WordPress provides the official Plugin Check tool:
composer require wp-cli/wp-cli-bundle
wp plugin install wordpress-plugin-check --activate
wp plugin activate wordpress-plugin-check
This tool catches security issues, best practices violations, and metadata problems.
Step 4: Test Against Multiple WordPress Versions
Reviewers test against the minimum version you declare and the latest version. Your plugin must work on both. Set up local environments with multiple WordPress versions using Docker or local installs.
Step 5: Get a Code Review
Ask a colleague or mentor to review your plugin before submission. Fresh eyes catch issues you're too close to see.
These prevention steps add maybe 2-3 hours of work before submission. Rejections and resubmission cycles take days or weeks. The math is obvious.
Tools That Help Catch Issues Early
You don't need to memorize every rule. Tools automate the checking.
WordPress Plugin Check
This is the official tool—what wp.org uses to prescreen submissions. WordPress Plugin Check runs comprehensive audits covering security, coding standards, and best practices. Run it locally before submitting.
PHPCS with WordPress Standards
PHP CodeSniffer with WordPress Coding Standards enforces style and detects common errors automatically. Set it up in your editor for real-time feedback.
WP HealthKit
WP HealthKit performs targeted security audits designed specifically for rejection prevention. The tool checks for unescaped output, missing nonces, inadequate sanitization, direct database queries, missing capability checks, and more. It's built by developers who understand the rejection review process intimately.
Unlike generic linters, WP HealthKit understands WordPress semantics. It knows when $_POST usage is legitimate versus dangerous. It understands context-sensitive escaping. It's designed to prevent the rejections you're trying to avoid.
Run these three tools in sequence:
- WP HealthKit for WordPress-specific security patterns
- PHPCS/WordPress Standards for coding style
- WordPress Plugin Check for comprehensive official compliance
This trio catches 95% of rejectable issues before submission.
Frequently Asked Questions
Can I resubmit immediately after fixing issues?
Yes. After addressing reviewer feedback, you can resubmit the same plugin slug immediately. There's no waiting period. WordPress reviewers expect iterative improvements. Submit → Receive feedback → Fix → Resubmit on the same day if possible. Most reviewers prioritize resubmissions because they show responsiveness and good faith effort to meet standards.
What if my plugin was rejected for a reason I don't understand?
Request clarification directly. When you resubmit, include a message asking the reviewer to elaborate on the specific issue. Cite the line numbers where you're uncertain, and ask which WordPress API or function would address their concern. Reviewers are educators—they want developers to succeed. Many will take time to explain nuanced issues if you ask respectfully.
Do I need to follow WordPress Coding Standards exactly?
Yes, functionally. The WordPress Plugin Review Team enforces these standards because they ensure long-term maintainability and consistency. You don't need to match formatting perfectly if you use automated tools like PHPCS, but you must address substantive issues like missing nonces, unescaped output, and improper API usage. Code style violations alone rarely cause rejection—security and functionality violations do.
How long does the review process take?
Initial reviews typically take 1-3 weeks, depending on queue length. If rejected, expect rereviews within 2-5 business days after resubmission. Holiday periods and WordPress release cycles can extend these timelines. If you don't hear back after three weeks, you can contact the review team directly through the WordPress.org plugin review contact form.
What's the difference between a security issue and a "best practice" violation?
Security issues expose your users to real attacks: XSS, CSRF, SQL injection, authentication bypass, privilege escalation, and data exposure. These are automatic rejections and non-negotiable fixes. Best practice violations are architectural or maintainability issues: improper hook usage, deprecated functions, missing cleanup, poor documentation. They're serious enough to warrant rejection but are addressed differently. Understand which category your feedback falls into so you can prioritize fixes appropriately.
Can I use jQuery or old JavaScript libraries?
WordPress bundles jQuery and includes many libraries. You should use bundled libraries whenever possible rather than including your own versions. If jQuery is deprecated in your target WordPress version, plan to migrate to vanilla JavaScript or modern frameworks. Reviewers increasingly flag plugins depending on outdated JavaScript libraries because they create security debt and bloat. Always check which libraries WordPress includes natively and leverage them.
Should I hire someone to review my plugin before submitting?
If you're uncertain about security practices, yes. A security-focused code review before submission saves weeks of back-and-forth rejections. Look for reviewers with WordPress plugin development experience specifically—they'll catch issues generic code reviewers miss. WP HealthKit can provide initial automated feedback; a human reviewer can validate architectural decisions and complex security patterns.
What if my plugin conflicts with popular plugins?
This is tested during review but rarely causes outright rejection. If conflicts are discovered, reviewers may request you fix integration issues or add compatibility layers. The expectation is that plugins coexist peacefully—yours shouldn't break others. Test your plugin alongside popular plugins like WooCommerce, ACF, Yoast, and Elementor before submitting to catch obvious conflicts.
Summary: Your Path to Approval
Plugin rejection isn't punishment—it's the process that keeps the WordPress ecosystem trustworthy. Thirty percent rejection rate reflects the seriousness of the standards.
The rejections you're reading about in forums, in Slack channels, among developer friends—they share common patterns. The issues are predictable. The fixes are known. The tools exist.
Before you submit:
- Run WP HealthKit to catch WordPress-specific security patterns
- Run PHPCS with WordPress Coding Standards
- Run the official Plugin Check tool
- Get a human code review if you're uncertain
- Test against your minimum declared WordPress version and the latest version
After rejection:
- Read the entire reviewer message carefully
- Address each point with specific code changes
- Reference WP HealthKit or PHPCS output showing the fix
- Resubmit with a professional response message
- Expect reapproval within 2-5 business days
The developers whose plugins breeze through approval—they're not smarter than you. They've internalized these standards through experience, or they use the tools that encode this experience automatically.
Your next submission can be approved. Use the tools. Follow the patterns. Respond professionally to feedback. You've got this.
Ready to audit your plugin? Upload it to WP HealthKit and get a detailed security report in seconds. See exactly which issues would trigger rejection, and get specific fixes for each one.