WP Manifestindependent plugin directory
manifest / ai / wpvdb

WPVDB - WordPress Vector Database WP Registry grade D+. High-severity findings · 3 findingsWP RegistryHigh-severity findings · 3 findingsOpen the reportD+

Native Vector Database for WordPress

★ 23stars
20release downloads
≈10active sites
v1.0.17latest · 5mo ago

Install

Download wpvdb.zip From the v1.0.17 release on GitHub, May 26, 2026

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

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/automattic/wpvdb/releases/download/v1.0.17/wpvdb.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 Vector Database (WPVDB)

A WordPress plugin that enables vector database functionality for semantic search and AI-powered content recommendations.

Features

  • Store and query vector embeddings in your WordPress database
  • Native vector type support for MySQL 8.0.32+ and MariaDB 11.7+
  • Fallback JSON storage for compatibility with older database versions
  • Generate embeddings using OpenAI's API or Automattic's API
  • Extend WP_Query with vector similarity search via vdb_vector_query
  • Automatic content chunking and embedding generation
  • Optional chunk summarization using AI
  • REST API endpoints for embedding generation and vector search
  • Background processing with Action Scheduler (if available)
  • Admin interface for managing vector database settings
  • Block editor integration

Requirements

  • WordPress 6.0+
  • PHP 7.4+
  • For optimal performance:
    • MySQL 8.0.32+ (with native VECTOR type) OR
    • MariaDB 11.7+ (with VECTOR type and VECTOR index)
  • Action Scheduler (recommended but not required)

Installation

  1. Upload the plugin files to the /wp-content/plugins/wpvdb directory, or install the plugin through the WordPress plugins screen.
  2. Activate the plugin through the 'Plugins' screen in WordPress.
  3. Configure your API key and settings through the Vector DB settings page.

Using the Docker Testing Environment

This plugin includes a Docker setup to test with both MySQL 8.0.32+ and MariaDB 11.7+ vector databases.

Starting the Environment

docker-compose up -d

This will start two separate WordPress instances:

Both instances have:

  • Admin username: admin
  • Admin password: password

Database Administration

  • MySQL Admin (Adminer): http://localhost:9180
  • MariaDB Admin (Adminer): http://localhost:9181
  • Login with:
    • System: MySQL (or MariaDB)
    • Server: mysql (or mariadb)
    • Username: root
    • Password: wordpress
    • Database: wordpress

Testing Vector Functionality

For MySQL 8.0.32+:

  1. Visit http://localhost:9080/wp-admin
  2. Configure API keys in Vector DB settings
  3. Generate embeddings for sample content
  4. Test vector search using the native MySQL vector type

For MariaDB 11.7+:

  1. Visit http://localhost:9081/wp-admin
  2. Configure API keys in Vector DB settings
  3. Generate embeddings for sample content
  4. Test vector search using MariaDB's vector implementation

Database Comparison

Feature MySQL 8.0.32+ MariaDB 11.7+
Vector Type VECTOR(dim) VECTOR(dim)
Max Dimensions 16383 No stated limit
Vector Index No native support VECTOR index type
Algorithm N/A Modified HNSW
Distance Functions STRING_TO_VECTOR function Built-in (VEC_DISTANCE_EUCLIDEAN, etc.)
Optimization Minimal Specialized for vector search

Usage

Generating Embeddings

// Generate an embedding for a text chunk
$embedding = WPVDB\Core::get_embedding('Your text to embed', 'text-embedding-3-small', 'https://api.openai.com/v1/', 'your-api-key');

// Store the embedding
WPVDB\REST::insert_embedding_row(
    $post_id,
    'chunk-0',
    'Your text to embed',
    'Optional summary',
    $embedding,
    'text-embedding-3-small', // model identifier
    'post',                   // doc_type (defaults to 'post')
    0                         // chunk_index (zero-based position)
);

Vector Search

// Search posts by vector similarity
$args = array(
    'post_type' => 'post',
    'posts_per_page' => 5,
    'vdb_vector_query' => 'Your search query'
);

$query = new WP_Query($args);

Chunk Text

// Chunk a long text into manageable pieces
$chunks = apply_filters('wpvdb_chunk_text', [], 'Your long text content');

// Use enhanced chunking with custom chunk size
$chunks = WPVDB\Core::enhanced_chunking([], 'Your long text content', 500);

REST API Endpoints

  • POST /wp-json/vdb/v1/embed - Generate embeddings for text
  • POST /wp-json/vdb/v1/vectors - Store vectors for content
  • POST /wp-json/vdb/v1/query - Perform vector search
  • GET /wp-json/vdb/v1/metadata - Get information about the vector database
  • POST /wp-json/wp/v2/wpvdb/reembed - Re-embed content from the block editor

Configuration

You can securely configure API keys by adding constants to your wp-config.php file:

define('WPVDB_OPENAI_API_KEY', 'your-openai-api-key');
define('WPVDB_AUTOMATTIC_API_KEY', 'your-automattic-api-key');

Documentation

For more detailed documentation, please see the Wiki.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the GPL v2 or later.

Releases

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

Tag
Published
Assets
Downloads
v1.0.17 latest
May 26, 2026 5mo ago
wpvdb.zip
14
May 19, 2026 5mo ago
wpvdb.zip
6

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

D+ grade

Security

WPVDB - WordPress Vector Database 1.0.17 · audited by WP Registry

High-severity findings.

1 high 2 medium
Audited release
1.0.17
Findings
3
Worst severity
high
Content hash
2bdb7e367fe08d3054778dd4…

Findings

  • high Stored XSS via REST-writable _wpvdb_embedded_model in the embedding metabox

    xss_stored

    _wpvdb_embedded_model (and sibling _wpvdb_embedded / _wpvdb_chunks_count / _wpvdb_embedded_date) is registered with show_in_rest true, type string, and auth_callback current_user_can('edit_posts'), with no sanitize_callback. A Contributor or Author can PUT /wp-json/wp/v2/posts/{id} with meta._wpvdb_embedded=true and meta._wpvdb_embedded_model set to HTML/JavaScript on a post they can edit (including a pending review post). Admin::render_embedding_meta_box then outputs the stored model with printf( esc_html__( 'Model: %s', 'wpvdb' ), $embedded_model ) — esc_html__() escapes only the translated format string, not the interpolated value. The same metabox is registered with add_meta_box() for auto-embed post types and still renders as HTML under the block editor. When an administrator opens the post to review or edit it, the payload executes in wp-admin as that administrator (session steal, new admin user, plugin install). Gutenberg's React status panel auto-escapes the same field and is not the sink. Subscriber cannot write the meta.

    includes/class-wpvdb-admin.php:1652-1675

    Recommendation

    Escape interpolated meta with esc_html() / esc_attr() in render_embedding_meta_box. Add sanitize_callback (e.g. sanitize_text_field) on register_post_meta for _wpvdb_embedded_model and _wpvdb_embedded_date. Prefer not exposing write access to these fields in REST, or restrict auth_callback to manage_options (the queue already writes them server-side).

  • medium REST /query and AJAX embedding-content leak all indexed chunks to edit_posts users

    information_disclosure

    Protected REST routes use default_permission_check(), which only requires the filterable capability edit_posts (Contributor+). handle_query returns id, doc_id, chunk_id, chunk_content, and summary for similarity hits with no current_user_can('read_post', $doc_id) (or password/private/draft) filter. Auto-embed runs on any post_status=publish, including password-protected posts, so a Contributor can semantically search and read protected/private-to-them bodies that WordPress core would not show. The same role can brute-force ajax_get_embedding_content (edit_posts + nonce wpvdb-admin, which enqueue_admin_assets localizes on every post.php/post-new.php) and retrieve chunk_content by sequential embedding id. If an administrator disables 'API Authentication', these endpoints become unauthenticated. /metadata is on the same gate and discloses db type/version and corpus size.

    includes/class-wpvdb-rest.php:132-188

    Recommendation

    Default wpvdb_required_capability to manage_options, or keep edit_posts but drop rows the current user cannot read_post() and never return chunk_content for password-protected/private/draft docs. Gate ajax_get_embedding_content with manage_options (it is only used from the embeddings admin screen). Do not treat require_auth=0 as anonymous full-corpus read without an explicit public-fields projection.

  • medium Contributor+ can re-embed any post and write arbitrary vectors using the site API key

    missing_capability

    POST /wp-json/wpvdb/v1/reembed and wp_ajax_wpvdb_reembed_post accept any post_id after only edit_posts (no current_user_can('edit_post', $post_id)). WPVDB_Queue::process_post deletes every embeddings row for that doc_id, clears embedding post meta, then calls Core::get_embedding() with Settings::get_api_key() — so a Contributor can wipe another author's index and bill the site's OpenAI/Automattic key. POST /wpvdb/v1/embed generates embeddings for attacker-supplied text against any doc_id using the same key (rate-limited 60/min). POST /wpvdb/v1/vectors inserts a caller-supplied vector and chunk_content for any doc_id, poisoning later /query and Query::maybe_vector_search results. ajax_reembed_post is reachable because enqueue_admin_assets prints nonce wpvdb-admin on post.php for every editor, and the classic metabox hard-codes that nonce. Reembed is not rate-limited. Subscriber is blocked unless Open Access is enabled.

    includes/class-wpvdb-rest.php:1177-1223

    Recommendation

    Require current_user_can('edit_post', $post_id) (or manage_options) on /reembed and ajax_reembed_post. Restrict /embed and /vectors to manage_options or to posts the user can edit, and bind doc_id to that post. Rate-limit reembed. Do not localize a powerful nonce on every post editor screen unless the corresponding AJAX is object-capped.

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.