-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add plugin checksums verification #26
Conversation
… into plugin-checksums
…d not be retrieved.
Multiple checksums act as a whitelist, accepting any one of the available checksums as proof for the file's integrity. Fixes #24
src/Checksum_Base_Command.php
Outdated
/** | ||
* Recursively get the list of files for a given path. | ||
* | ||
* @param string $path Root parse to start the recursive traversal in. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
path* ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 454a227
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be nice maybe to have a --report
option or similar to give more feedback but that's for another day...
features/checksum-plugin.feature
Outdated
Scenario: Multiple checksums for a single file are supported | ||
Given a WP install | ||
|
||
When I run `wp plugin install wptouch --version=4.3.22` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment here that wptouch
has sha256 (and md5) checksums with multiple values per file as it's not immediately obvious what's being tested here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought the scenario name Multiple checksums for a single file are supported
already gave that away...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha yeah it does, it just wasn't obvious to me why wptouch
should test it... ignore at will!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see. The choice of the plugin was based on the issue that reported the error: #24
I might add comments to link the tests to the relevant source issues then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in 464be76
$plugins = $fetcher->get_many( $all ? $this->get_all_plugin_names() : $args ); | ||
|
||
if ( empty( $plugins ) && ! $all ) { | ||
WP_CLI::error( 'You need to specify either one or more plugin slugs to check or use the --all flag to check all plugins.' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a test to provoke this error (and similarly for other errors/warnings - where feasible!)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in 9ef77d6
src/Checksum_Plugin_Command.php
Outdated
|
||
if ( empty( $this->errors ) ) { | ||
WP_CLI::success( | ||
count( $plugins ) > 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment if you do wp checksum plugin hello
then you get a warning about checksums not being available and Success: Plugin verifies against checksums.
at the end. It'd probably be better to use Utils\report_batch_operation_results()
instead once (after the error report if any), and also have a skip count to give it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you keep a $skips
count and then pass it it should work ok eg:
if ( ! empty( $this->errors ) ) {
$formatter = new \WP_CLI\Formatter(
$assoc_args,
array( 'plugin_name', 'file', 'message' )
);
$formatter->display_items( $this->errors );
}
$total = count( $plugins );
$failures = count( $this->errors );
$successes = $total - $failures - $skips;
Utils\report_batch_operation_results( 'plugin', 'verify', $total, $successes, $failures, $skips );
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed in 73efdd4
*/ | ||
private function get_all_plugin_names() { | ||
$names = array(); | ||
foreach ( get_plugins() as $file => $details ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if the all_plugins
filter should be applied here or not??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that would introduce a security vulnerability, as a malicious plugin could just filter itself out of the integrity check.
src/Checksum_Plugin_Command.php
Outdated
* @return array<string> Array of files with their relative paths. | ||
*/ | ||
private function get_plugin_files( $path ) { | ||
// TODO: Make sure this works for all types of plugins (single files, must-use, ...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for future proofing it should check here that $path
includes a directory and isn't just a bare file like hello.php
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes, thanks for catching the TODO, that does indeed still need an implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I just checked, and the current code just works with bare files like hello.php
as well. I don't think that we want to force the need for a folder for plugins.
However, must-use plugins are currently being ignored...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But $folder = trailingslashit( dirname( $this->get_absolute_path( $path ) ) );
where $path === "hello.php"
will just cause the plugins directory to be traversed. I was thinking of it doing something like:
if ( false === strpos( $path, '/' ) ) {
return array( $this->get_absolute_path( $path ) );
}
However, must-use plugins are currently being ignored...
I was wondering if they're ever stored on wordpress.org/plugins, and would checksums ever be provided?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re. single file. Yes, you are right. I did some deeper checking, and it only worked right now because the checksum could not be retrieved for hello.php
(as the hello-dolly
plugin is different on the repository).
Re. must-use plugins, I know that some people just move existing plugins into the must-use folder for client sites, to make sure they can't be disabled. This is usually done by adding something like the bedrock mu-plugins autoloader.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have fixed the single file issue (commits incoming). I suggest skipping the mu-checking for now and adding a separate issue for that, it might need more discussion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Single-file support: 9251a68
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issue re. mu-plugins: #27
src/Checksum_Base_Command.php
Outdated
foreach ( $files as $file_info ) { | ||
$pathname = substr( $file_info->getPathname(), strlen( $path ) ); | ||
if ( $file_info->isFile() && $this->filter_file( $pathname ) ) { | ||
$filtered_files[] = str_replace( $path, '', $file_info->getPathname() ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you reuse $pathname
here (also technically more correct!)...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally built it this way to have wp-content/plugins
be the root and everything else related to that.
This means that you have the plugin's folder included in the file name for error messages, like akismet/akismet.php
.
This serves two purposes:
- Allow proper delineation between plugins in a folder, and single-file plugins that don't have their own folder.
- Show whatever custom folder name the plugin happens to be installed in. Potentially, you can even have the same plugin installed in multiple versions, with differing checksum errors. Showing the folder helps you identify which one is being checked.
Can you elaborate why you think your suggestion is "technically more correct" ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just meant to do $filtered_files[] = $pathname
rather than the str_replace()
- it's a pet bugbear of mine when I see this str_replace()
pattern used on paths when it should be the "correct" substr()
- as used here for $pathanme
- but totally ignorable...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I can replace the str_replace()
with a substr()
anyway...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, nvm, I just noticed it myself... Doing the change now! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 22bc73e
Good stuff. We have our first headline release feature! |
Hey guys, really love this feature. I didn't see it explicitly mentioned in any of the changes for 1.5. Will this be included in WP CLI 1.5? |
Absolutely! |
@nateinaction Yes, it will be part of 1.5, coming soon! |
Thanks again guys! |
@schlessera was wondering should a release be made of |
Add plugin checksums verification
Initial implementation of the plugin checksum verification.
The WordPress.org infrastructure now calculates MD5 and SHA-256 checksums for all plugin files and stores them in a publically accessible way. You can find a specification of the current endpoint to retrieve the checksums here.
The
wp checksum plugin
command goes through some or all of the plugins installed on a machine, downloads the checksums for each plugin, and then verifies the downloaded checksums against freshly generated ones.Uses https://meta.trac.wordpress.org/ticket/3192
Resolves #15