WP Manifestindependent plugin directory
manifest / analytics / ab-testing-for-wp

A/B Testing for WordPress WP Registry grade D. High-severity findings · 5 findingsWP RegistryHigh-severity findings · 5 findingsOpen the reportD #9 in Analytics & Tracking

WordPress plugin which allow you to run A/B tests from anywhere within your content.

★ 61stars
181release downloads
≈10active sites
1.18.2latest · 6 years ago

Install

Download ab-testing-for-wp.zip From the 1.18.2 release on GitHub, Apr 14, 2020

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/jjj/ab-testing-for-wp/releases/download/1.18.2/ab-testing-for-wp.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

WordPress plugin which allow you to run A/B tests from anywhere within your content.

Utilize the new Gutenberg editor to create split tests to serve to your visitors and find out which variation works best.

Gutenberg Demo

Installing

  1. Download ab-testing-for-wp.zip found on the latest release
  2. Unzip contents and upload "ab-testing-for-wp" folder to the "/wp-content/plugins/" directory.
  3. Activate the plugin through the "Plugins" screen in WordPress.
  4. You can now add tests to your content!

Requirements

  • At least WordPress 5.0 (uses the new Gutenberg editor)

JavaScript Bundle Development

Requirements: Node.js

Clone the project and npm install.

Use the following commands:

# one time build
npm run build

# development watch mode for JavaScript
npm run dev

# prepare for release (clean, build, archive)
npm run release

Using Docker for development

Requirements: Composer, Docker

# Starting Docker container:
docker-compose up -d

Development WordPress install now runs at localhost:8000

./wp-content of the project root is synced with the development install's wp-content.

Look at docker-compose.yml for database passwords.

Testing and linting

This project is tested using Cypress and linted using eslint. These dependencies get installed with the project automatically.

ESLint

Linting makes sure the code style is in order. This will also be performed on the main repository when creating a pull request.

In order to run linting on your local environment run the following command from the root of the project:

npm run lint

Cypress

Running all end-to-end tests makes sure all functionality is still in place after updates to the code have been made.

Run all tests by entering the following command:

npm run test

There are a few extra command to help you test and develop locally:

# run local test environment and open Cypress
npm run test:dev

# tear down the setup environment and create a new one
npmr run e2e:setup-env

# reset the database to be a fresh WordPress install
npm run e2e:reset-db

Releases

23 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
1.18.2 latest
Apr 14, 2020 6 years ago
ab-testing-for-wp.zip
29
Apr 14, 2020 6 years ago
ab-testing-for-wp.zip
5
Apr 6, 2020 6 years ago
ab-testing-for-wp.zip
6
Feb 20, 2020 6 years ago
ab-testing-for-wp.zip
5
Feb 13, 2020 6 years ago
ab-testing-for-wp.zip
19
Feb 11, 2020 6 years ago
ab-testing-for-wp.zip
5
Feb 11, 2020 6 years ago
ab-testing-for-wp.zip
5
Feb 4, 2020 6 years ago
ab-testing-for-wp.zip
7
Feb 4, 2020 6 years ago
ab-testing-for-wp.zip
6
Feb 3, 2020 6 years ago
ab-testing-for-wp.zip
5
Jan 28, 2020 6 years ago
ab-testing-for-wp.zip
6
Jan 28, 2020 6 years ago
ab-testing-for-wp.zip
6
Jan 27, 2020 6 years ago
ab-testing-for-wp.zip
6
Jan 27, 2020 6 years ago
ab-testing-for-wp.zip
8
Jan 20, 2020 6 years ago
ab-testing-for-wp.zip
6
Jan 20, 2020 6 years ago
ab-testing-for-wp.zip
6
Jan 13, 2020 6 years ago
ab-testing-for-wp.zip
6
Jan 7, 2020 6 years ago
ab-testing-for-wp.zip
7
Jan 7, 2020 6 years ago
ab-testing-for-wp.zip
6
Jan 6, 2020 6 years ago
ab-testing-for-wp.zip
6
Jan 6, 2020 6 years ago
ab-testing-for-wp.zip
6
Nov 21, 2019 6 years ago
ab-testing-for-wp.zip
6
Nov 20, 2019 6 years ago
ab-testing-for-wp.zip
14

Active-site estimate ≈10 comes from the median of recent superseded releases. Method.

D grade

Security

A/B Testing for WordPress 1.18.2 · audited by WP Registry

High-severity findings.

2 high 3 medium
Audited release
1.18.2
Findings
5
Worst severity
high
Content hash
64f6bffe5ab783c213fa6f45…

Findings

  • high Contributor+ stored XSS via unescaped ab-test-block id attribute (CVE-2025-4587)

    xss_stored

    register_block_type('ab-testing-for-wp/ab-test-block') declares no PHP attribute schema or sanitize_callback. renderTest() takes $attributes['id'] from the block comment and wrapData() concatenates it raw into a data-test HTML attribute. Contributors can insert the inserter block (or convert an existing block) and set id in the code editor to a breakout such as x"><img src=x onerror=alert(document.domain)><!-- ; wp_kses_post does not rewrite JSON inside HTML comments, so the payload survives save and executes for every visitor of the published/previewed page. Variant HTML from GET /ab-testing-for-wp/v1/ab-test is also assigned with test.innerHTML in handleTestRender.ts (script tags would not run there, but the wrapData sink is a real HTML parser context). Unpatched; Wordfence/CVE-2025-4587, WordPress.org closed the plugin on 2025-06-26 for this issue.

    src/php/helpers/block-renderer.php:122-127

    Recommendation

    Escape the id with esc_attr() (and restrict it to a safe charset such as [A-Za-z0-9_-]). Register the block attributes in PHP with a sanitize_callback. Do not treat Gutenberg block-comment JSON as trusted for HTML attribute context.

  • high Inserter block and REST preview render arbitrary posts without a read_post check

    information_disclosure

    Three sinks load get_post($id) and run the_content with no current_user_can('read_post'), post_status, or post_type gate. (1) renderInsertedTest() is the render_callback for ab-test-block-inserter; a Contributor/Author sets attributes.id to any post ID (private page, someone else's draft, password-protected post) and the full body is echoed on the front end once the post is published (Authors publish themselves). (2) GET /ab-testing-for-wp/v1/get-test-content-by-post?id=N (permission_callback edit_posts only) returns apply_filters('the_content') wrapped in a full HTML document that also runs do_action('wp_head'), plus get_edit_post_link. (3) GET /get-posts-by-type?type=post returns $query->posts as JSON, including post_content and post_password for every published post of that type (password-protected posts are status=publish). Shortcode [ab-test id] similarly renders any abt4wp-test regardless of status. Observable: dump or publicly embed unpublished marketing copy, private pages, and password-protected post passwords.

    src/php/helpers/block-renderer.php:240-245

    Recommendation

    Require current_user_can('read_post', $id) and post_type === 'abt4wp-test' (and a public/publish status for front-end renders). For REST, also require edit_post on that ID. Do not JSON-encode full WP_Post rows; return id/title only and exclude post_password.

  • medium Test mutation and plugin options REST routes require only edit_posts

    missing_capability

    The overview admin pages are registered with manage_options, but POST /ab-testing-for-wp/v1/update-test and POST /ab-testing-for-wp/v1/options only check current_user_can('edit_posts'). updateTestData() json_decodes the body and ABTestManager::updateTest() array_merges it into the existing row then REPLACE INTO ab_testing_for_wp_ab_test, so a Contributor who knows a test id (they are printed as data-test on every front-end wrapper, and GET /get-tests-info also requires only edit_posts) can set isEnabled, postGoal, control, title, or postId for any site test — turning experiments off or pointing conversions at a different goal. handleOptions() writes any key/value into autoloaded option ab-testing-for-wp-options with no allow-list (including lastMigration, which forces installer ALTER/CREATE on the next init). Core REST cookie nonce applies; this is missing capability, not CSRF.

    src/php/registrations/register-rest.php:55-125

    Recommendation

    Gate update-test, options, get-tests-info, and stats on manage_options (or edit_post for the specific host post). Allow-list option keys. Do not let Contributors REPLACE test rows they do not own.

  • medium Admin database repair runs on an un-nonced GET and DROPs plugin tables

    csrf

    pages/advanced.php is included from RegisterAdminPage::advanced(), which is the manage_options submenu ab-testing-for-wp_advanced. The first lines run Installer::repair() when $_GET['repair-db']==='true' with no wp_verify_nonce, no check_admin_referer, and no POST requirement. repair() snapshots tracking, DROP TABLE the four ab_testing_for_wp_* tables, recreates them, clears lastMigration, re-runs migrations, and repopulates from a search for the block comment. A CSRF GET (img/script against /wp-admin/admin.php?page=ab-testing-for-wp_advanced&repair-db=true) while an administrator is logged in executes that path. If the request dies after DROP, all experiment metadata and logs are gone; even on success, repopulate depends on WP_Query search finding every block.

    src/php/pages/advanced.php:9-15

    Recommendation

    Use a POST form with check_admin_referer(), current_user_can('manage_options') immediately before repair(), and never trigger schema DROP from a GET parameter.

  • medium Plugin closed on WordPress.org for an unpatched 2025 XSS; no release since 1.18.2

    abandoned_plugin

    Header and README still ship Version 1.18.2, Requires at least 5.0, Tested up to 5.4. WordPress.org closed ab-testing-for-wp on 26 June 2025 with reason Security Issue the same day CVE-2025-4587 was published; Wordfence lists no patch. This GitHub-distributed zip is that same 1.18.2 tree (content hash 64f6bffe…). Combined with the additional unpatched IDOR/BAC/CSRF issues in this audit, sites cannot get a vendor fix via the update API.

    ab-testing-for-wp.php:6-12

    Recommendation

    Uninstall. WordPress.org already closed the listing; there is no patched release to update to. Replace with a maintained A/B testing plugin.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.