A store can report WooCommerce Subscriptions 9.1.0 while the plugin directory still contains an extra loader, an edited PHP file, or residue copied from an older package. The security update is necessary, but a trusted baseline comparison is what separates expected vendor files from local modifications and possible persistence.
Use this after the August Subscriptions advisory when file provenance is uncertain, the update was installed manually, a malware alert names the plugin directory, or production and staging behave differently even though both show the same version.
Quick answer
Download the approved 9.1.0 package from WooCommerce, hash it outside the web root, and compare its extracted tree with production. Quarantine unknown files without executing them, review legitimate customizations separately, inspect mu-plugins and writable sibling paths, then reinstall from the trusted package and verify subscriptions before declaring the file layer clean.
What to check first
- Record the production plugin path, reported version, directory owner, permissions, and most recent file modification times.
- Hash the approved ZIP and every production file using the same algorithm and normalized relative paths.
- Flag extra PHP files, changed vendor files, hidden files, recently modified loaders, and code outside the expected package tree.
- Inspect mu-plugins, uploads, cache directories, cron entries, and web-root include files for related persistence.
- Preserve suspicious files and access logs before reinstalling so the incident timeline remains available.
Why this usually happens
- A manual overwrite can leave files that no longer exist in the trusted package.
- Attackers often place loaders beside legitimate code so a plugin reinstall does not remove the entry point.
- Local edits to vendor files make checksum differences ambiguous unless the team has a documented customization baseline.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
shasum -a 256 woocommerce-subscriptions-9.1.0.zip
find clean/woocommerce-subscriptions -type f -print0 | sort -z | xargs -0 shasum -a 256 > clean.sha256
find wp-content/plugins/woocommerce-subscriptions -type f -print0 | sort -z | xargs -0 shasum -a 256 > production.sha256
diff -u clean.sha256 production.sha256
find wp-content -type f -name '*.php' -mtime -14 -print
Diagnostic table
Use this table to connect the observed behavior to evidence and a verification step.
| Action | Evidence to collect | How to verify |
| Capture hashes, file metadata, relevant logs, and a restorable backup. | Record the production plugin path, reported version, directory owner, permissions, and most recent file modification times. | The production plugin tree matches the trusted package after approved exclusions. |
| Quarantine unexplained artifacts outside the web root with restricted permissions. | Hash the approved ZIP and every production file using the same algorithm and normalized relative paths. | No related executable artifact exists in mu-plugins, uploads, cache, cron, or web-root include paths. |
| Replace the plugin directory from the trusted package instead of merging files. | Flag extra PHP files, changed vendor files, hidden files, recently modified loaders, and code outside the expected package tree. | A controlled renewal and scheduled action complete with no duplicate or altered behavior. |
| Inspect adjacent persistence points and rotate secrets exposed during the incident. | Inspect mu-plugins, uploads, cache directories, cron entries, and web-root include files for related persistence. | A second file comparison after the observation window shows no unexplained changes. |
Decision rule
Treat the file layer as clean only when production matches the approved package or every documented difference has a named owner and reviewed purpose. Escalate any executable extra file, obfuscated code, unexpected loader, or recurring change.
Test scenarios to run
Run the same controlled fixture across these branches. Write down the expected result before testing so a surprising response is easy to identify.
| Scenario | Fixture | Expected result |
| Trusted package | Approved WooCommerce download and recorded checksum | Archive source and hash are documented before extraction |
| Tree comparison | Clean extraction and production plugin directory | Added, missing, and changed files are listed by relative path |
| Sibling persistence | mu-plugins, uploads, cache, web root, and cron | No related loader or executable artifact survives outside the plugin folder |
| Functional recovery | Disposable active subscription and sandbox gateway | Renewal, status, webhook, and scheduled action complete once |
Safe fix order
Use a sequence that makes each result easy to prove. Stop when new evidence changes the scope or owner of the problem.
- Capture hashes, file metadata, relevant logs, and a restorable backup.
- Quarantine unexplained artifacts outside the web root with restricted permissions.
- Replace the plugin directory from the trusted package instead of merging files.
- Inspect adjacent persistence points and rotate secrets exposed during the incident.
- Run the subscription fixture and monitor file changes through the observation window.
Production verification checklist
- The production plugin tree matches the trusted package after approved exclusions.
- No related executable artifact exists in mu-plugins, uploads, cache, cron, or web-root include paths.
- A controlled renewal and scheduled action complete with no duplicate or altered behavior.
- A second file comparison after the observation window shows no unexplained changes.
What to tell the client or owner
Provide package source and hash, added and changed paths, preserved evidence location, approved exclusions, removed persistence, reinstalled version, fixture results, secret rotations, and observation owner.
Mistakes to avoid
- Do not trust the version header as a file-integrity result.
- Do not delete unknown PHP before preserving a copy and its metadata.
- Do not merge a clean ZIP over an untrusted directory and leave orphan files behind.
- Do not upload evidence archives to a public media or backup path.
Questions teams ask during testing
Can WP-CLI verify premium plugin checksums?
WordPress.org checksums do not cover every premium package. Build a baseline from the approved WooCommerce archive and keep its source and hash.
Are all extra files malicious?
No. Local customizations, logs, and deployment artifacts can be legitimate, but each difference needs an owner and purpose.
Why inspect mu-plugins too?
A loader outside the normal plugin directory can restore or call compromised code after the main plugin is replaced.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, security, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, compare a WooCommerce plugin against a trusted baseline.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Helpful references