Skip to content

Add Write File Check to detect plugin directory writes#1137

Merged
davidperezgar merged 14 commits into
trunkfrom
665-check-asks-users-to-editwrite-to-plugin-use-uploads-folder
May 19, 2026
Merged

Add Write File Check to detect plugin directory writes#1137
davidperezgar merged 14 commits into
trunkfrom
665-check-asks-users-to-editwrite-to-plugin-use-uploads-folder

Conversation

@davidperezgar
Copy link
Copy Markdown
Member

@davidperezgar davidperezgar commented Dec 27, 2025

Fixes #665

Implements a new check to detect when plugins save data in the plugin folder.

Plugin folders are deleted when upgraded, so using them to store any data is problematic. This check helps developers identify these issues and directs them to use the uploads directory or database instead.

Changes Made

1. WriteFileSniff (PHPCS Sniff)

Created phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/WriteFileSniff.php:

  • Extends AbstractFunctionParameterSniff to detect file write functions
  • Monitors functions: fwrite, fputs, file_put_contents, touch, copy, rename, copy_dir, move_dir, unzip_file
  • Detects plugin directory indicators:
    • Constants: WP_PLUGIN_DIR, WP_PLUGIN_URL, PLUGINDIR, WPINC, WP_CONTENT_DIR, WP_CONTENT_URL
    • Functions: plugins_url(), plugin_dir_path(), plugin_dir_url()
    • Magic constants: __FILE__, __DIR__
  • Allows safe paths using wp_upload_dir(), wp_tempnam(), get_temp_dir()
  • Provides clear error messages with remediation guidance

2. Write_File_Check Class

Updated includes/Checker/Checks/Plugin_Repo/Write_File_Check.php:

  • Added proper description
  • Added documentation URL
  • Integrates the sniff into Plugin Check

3. Test Coverage

Test Plugins:

  • test-plugin-write-file-with-errors/: Contains 7 examples of incorrect usage
  • test-plugin-write-file-without-errors/: Contains examples of correct usage

PHPUnit Tests:

  • Write_File_Check_Tests.php: Tests the check class
  • WriteFileUnitTest.php and WriteFileUnitTest.inc: Tests the sniff directly

4. Configuration

  • Added PluginCheck.CodeAnalysis.WriteFile rule to phpcs-sniffs/PluginCheck/ruleset.xml

Limitations

The sniff uses static analysis and can only detect file write operations where the path is directly specified in the function call. It cannot detect:

  • Paths stored in variables before the function call
  • Dynamically constructed paths using complex logic
  • File writes through wrapper functions or classes

This limitation is acceptable as it catches the most common cases.

Related Resources

Acknowledgments

This check is based on the calls_write_file_warning detection logic from the internal plugin review scanner developed by @frantorres, which has been successfully identifying these issues during manual reviews. This implementation makes that same detection available to plugin developers as an automated check.

@davidperezgar davidperezgar linked an issue Dec 27, 2025 that may be closed by this pull request
@davidperezgar davidperezgar added this to the 1.9.0 milestone Dec 27, 2025
@davidperezgar davidperezgar modified the milestones: 1.9.0, 2.0.0 Mar 15, 2026
@davidperezgar davidperezgar marked this pull request as ready for review April 15, 2026 20:27
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 15, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: davidperezgar <davidperez@git.wordpress.org>
Co-authored-by: ernilambar <nilambar@git.wordpress.org>
Co-authored-by: frantorres <frantorres@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Comment thread includes/Checker/Checks/Plugin_Repo/Write_File_Check.php Outdated
Comment thread includes/Checker/Checks/Plugin_Repo/Write_File_Check.php Outdated
davidperezgar and others added 2 commits April 16, 2026 21:42
Co-authored-by: Nilambar Sharma <ernilambar@users.noreply.github.com>
Co-authored-by: Nilambar Sharma <ernilambar@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new “Write File” check to Plugin Check, implemented as a PHPCS sniff + a corresponding check wrapper, to flag plugins that write generated/user data into the plugin directory (which gets wiped on upgrades).

Changes:

  • Introduces a new PHPCS sniff (WriteFileSniff) to detect common file write/copy/move operations targeting plugin-directory related paths, with allowlisting for uploads/temp paths.
  • Registers a new Write_File_Check in the default check repository and wires the sniff into the PluginCheck PHPCS ruleset.
  • Adds PHPUnit + sniff unit tests and test plugin fixtures (with and without violations).

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/phpunit/tests/Checker/Checks/Write_File_Check_Tests.php Adds PHPUnit coverage for the new check wrapper behavior.
tests/phpunit/testdata/plugins/test-plugin-write-file-without-errors/load.php Fixture plugin demonstrating allowed/safe write locations.
tests/phpunit/testdata/plugins/test-plugin-write-file-with-errors/load.php Fixture plugin demonstrating disallowed write locations.
tests/phpunit/testdata/plugins/test-plugin-write-file-with-errors/file-operations.php Additional fixture file to validate multi-file scanning + indirect path cases.
phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/WriteFileUnitTest.php Adds PHPCS sniff unit test harness for WriteFileSniff.
phpcs-sniffs/PluginCheck/Tests/CodeAnalysis/WriteFileUnitTest.inc Provides the test cases (expected errors/ok cases) for the sniff unit test.
phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/WriteFileSniff.php Implements the new static-analysis detection logic for plugin-directory write operations.
phpcs-sniffs/PluginCheck/ruleset.xml Enables the new sniff in the PluginCheck PHPCS standard.
includes/Checker/Default_Check_Repository.php Registers the new check in the default check set.
includes/Checker/Checks/Plugin_Repo/Write_File_Check.php Adds the new check wrapper that runs the sniff within Plugin Check.
composer.lock Updates the locked sniffs package version reference to include this new rule.
Comments suppressed due to low confidence (2)

includes/Checker/Checks/Plugin_Repo/Write_File_Check.php:19

  • The class docblock description says this check detects loading files from external sites, but this check actually runs the WriteFile PHPCS sniff to detect writes into the plugin folder. Please update the docblock summary to reflect what the check does.
/**
 * Check to detect loading files from external sites.
 *
 * @since 2.0.0

includes/Checker/Checks/Plugin_Repo/Write_File_Check.php:41

  • Several new docblocks use the placeholder "@SInCE n.e.x.t." which is inconsistent with the rest of the codebase where released version numbers are used (e.g., other checks in this directory). Please replace these placeholders with the correct version for when this check will ship, and keep the @since tags consistent within the file.
	/**
	 * Bitwise flags to control check behavior.
	 *
	 * @since n.e.x.t.
	 * @var int
	 */
	protected $flags = 0;

	/**
	 * Gets the categories for the check.
	 *
	 * Every check must have at least one category.
	 *
	 * @since n.e.x.t.
	 *
	 * @return array The categories for the check.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread includes/Checker/Checks/Plugin_Repo/Write_File_Check.php Outdated
Comment thread phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/WriteFileSniff.php Outdated
Comment thread phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/WriteFileSniff.php Outdated
davidperezgar and others added 2 commits May 15, 2026 16:35
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment thread phpcs-sniffs/PluginCheck/Sniffs/CodeAnalysis/WriteFileSniff.php Outdated
davidperezgar and others added 2 commits May 16, 2026 09:09
@davidperezgar davidperezgar merged commit 7952114 into trunk May 19, 2026
27 checks passed
@davidperezgar davidperezgar deleted the 665-check-asks-users-to-editwrite-to-plugin-use-uploads-folder branch May 19, 2026 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check: Asks users to edit/write to plugin (use uploads folder)

4 participants