Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/checks.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
| plugin_review_phpcs | plugin_repo | Runs PHP_CodeSniffer to detect certain best practices plugins should follow for submission on WordPress.org, including heredoc usage detection. | [Learn more](https://developer.wordpress.org/plugins/plugin-basics/best-practices/) |
| direct_db_queries | security, plugin_repo | Checks the usage of direct database queries, which should be avoided. | [Learn more](https://developer.wordpress.org/apis/database/) |
| direct_db | security, plugin_repo | Checks the escaping in direct database queries. | [Learn more](https://developer.wordpress.org/apis/database/) |
| public_content_export | security | Detects when post content is exported through a public surface without an apparent access-control guard. | [Learn more](https://developer.wordpress.org/plugins/wordpress-org/plugin-guidelines/) |
| performant_wp_query_params | performance | Checks for potentially slow database queries when using <code>WP_Query</code> | [Learn more](https://developer.wordpress.org/apis/database/) |
| enqueued_scripts_in_footer | performance | Checks whether a loading strategy is explicitly set for JavaScript files, as loading scripts in the footer is usually desired. | [Learn more](https://developer.wordpress.org/plugins/) |
| enqueued_resources | plugin_repo, performance | Checks whether scripts and styles are properly enqueued using the recommended way. | [Learn more](https://developer.wordpress.org/plugins/) |
Expand Down
128 changes: 128 additions & 0 deletions includes/Checker/Checks/Security/Public_Content_Export_Check.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php
/**
* Class Public_Content_Export_Check.
*
* @package plugin-check
*/

namespace WordPress\Plugin_Check\Checker\Checks\Security;

use WordPress\Plugin_Check\Checker\Check_Categories;
use WordPress\Plugin_Check\Checker\Check_Result;
use WordPress\Plugin_Check\Checker\Checks\Abstract_PHP_CodeSniffer_Check;
use WordPress\Plugin_Check\Traits\Amend_Check_Result;
use WordPress\Plugin_Check\Traits\Stable_Check;

/**
* Advisory check for plugins that export restricted post content through
* alternative public surfaces without apparent access-control guards.
*
* This check detects when post content (post_content, get_the_content(),
* the_content, etc.) is written to a file or exposed through a public
* endpoint. It flags the pattern as a warning because third-party access
* control is not statically knowable — the finding prompts a manual
* access-policy review rather than asserting a vulnerability.
*
* The check looks for code that both:
* - obtains or renders post bodies; and
* - writes that output to a file or exposes it through a public surface.
*
* Potential signals include directly reading post_content, exporting
* content without an explicit post_password_required() guard, and
* generating a public cache or static file from the current user context.
*
* @since 2.1.0
*/
class Public_Content_Export_Check extends Abstract_PHP_CodeSniffer_Check {

use Amend_Check_Result;
use Stable_Check;

/**
* Bitwise flags to control check behavior.
*
* @since 2.1.0
* @var int
*/
protected $flags = 0;

/**
* Gets the categories for the check.
*
* @since 2.1.0
*
* @return array The categories for the check.
*/
public function get_categories() {
return array( Check_Categories::CATEGORY_SECURITY );
}

/**
* Returns an associative array of arguments to pass to PHPCS.
*
* @since 2.1.0
*
* @param Check_Result $result The check result to amend.
* @return array An associative array of PHPCS CLI arguments.
*/
protected function get_args( Check_Result $result ) {
return array(
'extensions' => 'php',
'standard' => 'PluginCheck',
'sniffs' => 'PluginCheck.Security.PublicContentExport',
);
}

/**
* Gets the description for the check.
*
* @since 2.1.0
*
* @return string Description.
*/
public function get_description(): string {
return __( 'Detects when post content is exported through a public surface without an apparent access-control guard.', 'plugin-check' );
}

/**
* Gets the documentation URL for the check.
*
* @since 2.1.0
*
* @return string The documentation URL.
*/
public function get_documentation_url(): string {
return __( 'https://developer.wordpress.org/plugins/wordpress-org/plugin-guidelines/#wordpress-org-plugin-guidelines', 'plugin-check' );
}

/**
* Amends the given result for a plugin context, customizing the message
* for post-content export warnings.
*
* @since 2.1.0
*
* @param Check_Result $result The check result to amend.
* @param bool $error Whether this is an error (true) or a warning (false).
* @param string $message The original message from the sniff.
* @param string $code The sniff error/warning code.
* @param string $file The file where the issue was found.
* @param int $line The line number.
* @param int $column The column number.
* @param string $docs Documentation URL override.
* @param int $severity Severity level (1-9 per PHPCS convention).
*/
protected function add_result_message_for_file( $result, $error, $message, $code, $file, $line = 0, $column = 0, $docs = '', $severity = 5 ) {
// All findings from this check are advisory warnings.
parent::add_result_message_for_file(
$result,
false,
$message,
$code,
$file,
$line,
$column,
$docs,
$severity
);
}
}
1 change: 1 addition & 0 deletions includes/Checker/Default_Check_Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ private function register_default_checks() {
'localhost' => new Checks\Plugin_Repo\Localhost_Check(),
'no_unfiltered_uploads' => new Checks\Plugin_Repo\No_Unfiltered_Uploads_Check(),
'trademarks' => new Checks\Plugin_Repo\Trademarks_Check(),
'public_content_export' => new Checks\Security\Public_Content_Export_Check(),
'non_blocking_scripts' => new Checks\Performance\Non_Blocking_Scripts_Check(),
'offloading_files' => new Checks\Plugin_Repo\Offloading_Files_Check(),
'write_file' => new Checks\Plugin_Repo\Write_File_Check(),
Expand Down
Loading
Loading