[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fqTkG8oCNwuTnSVePGz9U2dKWcFJ5DkC8Y3VcqV_i-NY":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-39575","custom-query-blocks-authenticated-contributor-stored-cross-site-scripting-2","Custom Query Blocks \u003C= 5.5.0 - Authenticated (Contributor+) Stored Cross-Site Scripting","The Custom Query Blocks plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 5.5.0 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","post-type-archive-mapping",null,"\u003C=5.5.0","5.6.0","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-02-12 00:00:00","2026-04-15 21:30:27",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F2d8d7a10-8086-48f7-af6f-6abfe7767fbc?source=api-prod",63,[22,23,24,25],"includes\u002Fblocks\u002Fcustom-post-types\u002Fclass-custom-post-types.php","includes\u002Fclass-functions.php","post-type-archive-mapping.php","readme.txt","researched",false,3,"h1>, \u003Ch2>, etc.).\n            If `custom_posts` does:\n            ```php\n            $title_tag = $attributes['titleTag'];\n            $markup .= \"\u003C$title_tag>\" . get_the_title() . \"\u003C\u002F$title_tag>\";\n            ```\n            And `title_tag` is only sanitized with `sanitize_text_field` or `esc_html`.\n            `esc_html(\"h1 onmouseover=alert(1)\")` -> `h1 onmouseover=alert(1)`.\n            This would result in: `\u003Ch1 onmouseover=alert(1)>Title\u003C\u002Fh1>`. **BINGO.**\n\n            Let's look at the `custom_posts` initialization again.\n            ```php\n            $attributes['displayTitle']        = isset( $attributes['displayTitle'] ) ? esc_html( $attributes['displayTitle'] ) : true;\n            ```\n            Wait, if `displayTitle` is used as the tag name? No, that doesn't make sense.\n            But the changelog *explicitly* says `title tag`.\n\n            Let's assume the block name is `ptam\u002Fcustom-post-types`.\n            Let's assume there's an attribute `titleTag`.\n\n            Wait, look at `readme.txt` again.\n            `* Enhancement\u002Ffix: Blocks are now compatible with Block.json v3.`\n            This confirms it's a Gutenberg block.\n\n    *   Contributor role.\n    *   ","The Custom Query Blocks plugin is vulnerable to Stored Cross-Site Scripting (XSS) via the 'imageAlignment' attribute in Gutenberg blocks. Authenticated attackers with contributor-level permissions can inject malicious JavaScript into the 'style' attribute of post grid elements, which executes in the browser of any user viewing the affected page.","\u002F\u002F includes\u002Fblocks\u002Fcustom-post-types\u002Fclass-custom-post-types.php (approx lines 80-84 and 94-98)\n$list_item_markup .= sprintf(\n    '\u003Cdiv class=\"ptam-block-post-grid-image\" %3$s>\u003Ca href=\"%1$s\" rel=\"bookmark\">%2$s\u003C\u002Fa>\u003C\u002Fdiv>',\n    esc_url( get_permalink( $post_id ) ),\n    get_avatar( $post_author, $attributes['avatarSize'] ),\n    'grid' === $attributes['postLayout'] ? \"style='text-align: {$image_alignment}'\" : ''\n);\n\n---\n\n\u002F\u002F includes\u002Fblocks\u002Fcustom-post-types\u002Fclass-custom-post-types.php (line 441-444, inferred from patch)\n$list_items_markup .= sprintf(\n    '\u003Cdiv class=\"ptam-block-post-grid-image\" %3$s>\u003Ca href=\"%1$s\" rel=\"bookmark\">%2$s\u003C\u002Fa>\u003C\u002Fdiv>',\n    esc_url( get_permalink( $post_id ) ),\n    $this->get_profile_image( $attributes, $post_thumb_id, $post->post_author, $post->ID ),\n    'grid' === $attributes['postLayout'] ? \"style='text-align: {$attributes['imageAlignment']}'\" : ''\n);\n\n---\n\n\u002F\u002F includes\u002Fclass-functions.php (lines 50-55)\npublic static function sanitize_attribute( $attributes, $attribute, $type = 'text' ) {\n    if ( isset( $attributes[ $attribute ] ) ) {\n        switch ( $type ) {\n            case 'text':\n                return sanitize_text_field( $attributes[ $attribute ] );","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpost-type-archive-mapping\u002F5.5.0\u002Fincludes\u002Fblocks\u002Fcustom-post-types\u002Fclass-custom-post-types.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpost-type-archive-mapping\u002F5.6.0\u002Fincludes\u002Fblocks\u002Fcustom-post-types\u002Fclass-custom-post-types.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpost-type-archive-mapping\u002F5.5.0\u002Fincludes\u002Fblocks\u002Fcustom-post-types\u002Fclass-custom-post-types.php\t2026-02-20 04:43:08.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpost-type-archive-mapping\u002F5.6.0\u002Fincludes\u002Fblocks\u002Fcustom-post-types\u002Fclass-custom-post-types.php\t2026-03-06 22:17:08.000000000 +0000\n@@ -66,7 +66,7 @@\n \t\t\t'center',\n \t\t\t'right',\n \t\t\t);\n-\t\t$image_alignment          = Functions::sanitize_attribute( $attributes, 'imageAlignment', 'text' );\n+\t\t$image_alignment          = Functions::sanitize_attribute( $attributes, 'imageAlignment', 'attr' );\n \t\tif ( ! in_array( $image_alignment, $image_alignments_options, true ) ) {\n \t\t\t$image_alignment = 'left';\n \t\t}\n@@ -80,7 +80,7 @@\n \t\t\t\t\t\t'\u003Cdiv class=\"ptam-block-post-grid-image\" %3$s>\u003Ca href=\"%1$s\" rel=\"bookmark\">%2$s\u003C\u002Fa>\u003C\u002Fdiv>',\n \t\t\t\t\t\tesc_url( get_permalink( $post_id ) ),\n \t\t\t\t\t\tget_avatar( $post_author, $attributes['avatarSize'] ),\n-\t\t\t\t\t\t'grid' === $attributes['postLayout'] ? \"style='text-align: {$image_alignment}'\" : ''\n+\t\t\t\t\t\t'grid' === $attributes['postLayout'] ? \"style='text-align: \" . esc_attr( $image_alignment ) . \"'\" : ''\n \t\t\t\t\t);\n \t\t\t\t} else {\n \t\t\t\t\t$list_item_markup .= sprintf(\n@@ -94,7 +94,7 @@\n \t\t\t\t\t\t'\u003Cdiv class=\"ptam-block-post-grid-image\" %3$s>\u003Ca href=\"%1$s\" rel=\"bookmark\">%2$s\u003C\u002Fa>\u003C\u002Fdiv>',\n \t\t\t\t\t\tesc_url( get_permalink( $post_id ) ),\n \t\t\t\t\t\twp_get_attachment_image( $post_thumb_id, $post_thumb_size ),\n-\t\t\t\t\t\t'grid' === $attributes['postLayout'] ? \"style='text-align: {$image_alignment}'\" : ''\n+\t\t\t\t\t\t'grid' === $attributes['postLayout'] ? \"style='text-align: \" . esc_attr( $image_alignment ) . \"'\" : ''\n \t\t\t\t\t);\n \t\t\t} else {\n \t\t\t\t$list_item_markup .= sprintf(\n@@ -441,7 +441,7 @@\n \t\t\t\t\t\t\t'\u003Cdiv class=\"ptam-block-post-grid-image\" %3$s>\u003Ca href=\"%1$s\" rel=\"bookmark\">%2$s\u003C\u002Fa>\u003C\u002Fdiv>',\n \t\t\t\t\t\t\tesc_url( get_permalink( $post_id ) ),\n \t\t\t\t\t\t\t$this->get_profile_image( $attributes, $post_thumb_id, $post->post_author, $post->ID ),\n-\t\t\t\t\t\t\t'grid' === $attributes['postLayout'] ? \"style='text-align: {$attributes['imageAlignment']}'\" : ''\n+\t\t\t\t\t\t\t'grid' === $attributes['postLayout'] ? \"style='text-align: \" . esc_attr( $attributes['imageAlignment'] ) . \"'\" : ''\n \t\t\t\t\t\t);\n \t\t\t\t\t} else {\n \t\t\t\t\t\t$list_items_markup .= sprintf(\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpost-type-archive-mapping\u002F5.5.0\u002Fincludes\u002Fclass-functions.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpost-type-archive-mapping\u002F5.6.0\u002Fincludes\u002Fclass-functions.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpost-type-archive-mapping\u002F5.5.0\u002Fincludes\u002Fclass-functions.php\t2021-03-25 13:40:36.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpost-type-archive-mapping\u002F5.6.0\u002Fincludes\u002Fclass-functions.php\t2026-03-06 22:17:08.000000000 +0000\n@@ -50,6 +50,8 @@\n \tpublic static function sanitize_attribute( $attributes, $attribute, $type = 'text' ) {\n \t\tif ( isset( $attributes[ $attribute ] ) ) {\n \t\t\tswitch ( $type ) {\n+\t\t\t\tcase 'attr':\n+\t\t\t\t\treturn esc_attr( $attributes[ $attribute ] );\n \t\t\t\tcase 'text':\n \t\t\t\t\treturn sanitize_text_field( $attributes[ $attribute ] );\n \t\t\t\tcase 'bool':","The exploit requires Contributor-level authentication. An attacker can create or edit a post and add a Custom Post Types block. By modifying the block's attributes via the editor (or manually crafting the block comment in the post content), the attacker sets the 'imageAlignment' attribute to a payload that breaks out of an HTML attribute, such as `left' onmouseover='alert(1)`. The 'postLayout' attribute must be set to 'grid'. When a user views the post, the unescaped 'imageAlignment' attribute is rendered directly into a 'style' attribute, triggering the execution of the injected JavaScript.","gemini-3-flash-preview","2026-04-21 00:09:04","2026-04-21 00:09:54",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","5.5.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fpost-type-archive-mapping\u002Ftags\u002F5.5.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fpost-type-archive-mapping.5.5.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fpost-type-archive-mapping\u002Ftags\u002F5.6.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fpost-type-archive-mapping.5.6.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fpost-type-archive-mapping\u002Ftags"]