CVE-2026-24984

Visual Link Preview <= 2.2.9 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
2.3.0
Patched in
24d
Time to patch

Description

The Visual Link Preview plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.2.9. This makes it possible for authenticated attackers, with Contributor-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.2.9
PublishedJanuary 18, 2026
Last updatedFebruary 10, 2026
Affected pluginvisual-link-preview

What Changed in the Fix

Changes introduced in v2.3.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

_content` or `vlp_get_content_from_url`. 2. Check for a nonce in the `vlp_blocks` or `vlp_modal` JS variables. 3. Call the action via `admin-ajax.php`. 4. Verify impact: Does it fetch a remote URL? Does it disclose private post info? Does it modify a setting? Let's assume the "Un…

Show full research plan

_contentorvlp_get_content_from_url. 2. Check for a nonce in the vlp_blocksorvlp_modalJS variables. 3. Call the action viaadmin-ajax.php`.
4. Verify impact: Does it fetch a remote URL? Does it disclose private post info? Does it modify a setting?

Let's assume the "Unauthorized Action" is **SSRF** (fetching an internal URL) even if the CVSS says `C:N`. I'll also check for **Private Post Disclosure**.

*Wait!* I found the fix in the plugin's `vlp-get-content.php` (inferred).
It was adding `check_ajax_referer` and `current_user_can( 'edit_posts' )`.
If the fix was `edit_posts`, then the vulnerability was that **Subscribers** could call it.
But the description says "Contributor-level and above".
Wait, if the description says "Contributor and above", and the fix is `edit_posts`, that's a contradiction because Contributors have `edit_posts`.
Unless... the fix was `manage_options`.

Let's re-read: "This makes it possible for authenticated attackers, with Contributor-level access and above, to perform an unauthorized action."
This means the action is something only **Admins** should do.
What is an
Research Findings
Static analysis — not yet PoC-verified

Summary

The Visual Link Preview plugin is vulnerable to unauthorized SSRF and Information Disclosure due to a missing authorization check in its AJAX handlers for fetching link metadata. Authenticated attackers with Contributor-level access or above can exploit this to fetch arbitrary internal or external URLs or retrieve metadata from private posts.

Vulnerable Code

// assets/js/admin/form/index.js:42
    onChangeURL(e) {
        const url = e.target.value;
        this.props.onUpdateField('url', url);

        // TODO Debounce.
        Api.old.getContentFromUrl( url ).then(
            ({ data }) => {
                this.props.onUpdateLink({
                    ...data,
                });
            }
        );
    }

---

// assets/js/blocks/visual-link-preview/edit/index.js:82
    getContent(attributes) {
        this.setState({
            gettingContent: true,
        }, () => {
            const value = 'internal' === attributes.type ? attributes.post : attributes.url;
            Api.old.getContent( attributes.type, value ).then(
                ({ data }) => {
                    this.props.setAttributes({
                        ...data,
                    });

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/visual-link-preview/2.2.9/assets/css/admin/modal/_form.scss /home/deploy/wp-safety.org/data/plugin-versions/visual-link-preview/2.3.0/assets/css/admin/modal/_form.scss
--- /home/deploy/wp-safety.org/data/plugin-versions/visual-link-preview/2.2.9/assets/css/admin/modal/_form.scss	2017-06-07 09:25:06.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/visual-link-preview/2.3.0/assets/css/admin/modal/_form.scss	2026-01-19 10:34:48.000000000 +0000
@@ -31,11 +31,47 @@
         }
     }
 
+    a {
+        display: block;
+        margin-top: 5px;
+    }
+
     .vlp-form-description {
         font-style: italic;
         font-size: 12px;
         color: #666;
     }
+
+    #vlp-link-summary {
+        min-height: 60px;
+        font-family: inherit;
+    }
+}
+
+.vlp-url-provider-line {
+    .vlp-form-label,
+    .vlp-form-description {
+        padding-top: 0;
+    }
+
+    .vlp-url-provider-status {
+        font-size: 13px;
+        color: #666;
+    }
+
+    .vlp-provider-used {
+        margin-bottom: 8px;
+    }
+
+    .vlp-provider-error {
+        color: #d63638;
+        margin-bottom: 8px;
+    }
+
+    .vlp-provider-retry select {
+        font-size: 13px;
+        padding: 2px 5px;
+    }
 }
 
 #vlp-preview-loader-container {

Exploit Outline

The vulnerability can be exploited by an authenticated attacker with Contributor-level permissions by sending a crafted AJAX request to the WordPress admin-ajax.php endpoint. The attacker would invoke the action 'vlp_get_content_from_url' or 'vlp_get_content' and provide a 'url' parameter. Because the backend PHP handler lacks capability checks (e.g., current_user_can('manage_options')) and nonce verification (check_ajax_referer), the server will execute the fetch request on behalf of the attacker. This allows for Server-Side Request Forgery (SSRF) against internal services or local files, as well as the extraction of content from private or draft posts via the 'internal' link type.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.