Changeset 3430727
- Timestamp:
- 01/01/2026 07:31:29 PM (3 months ago)
- Location:
- modular-blocks-core/trunk
- Files:
-
- 6 edited
-
assets/js/admin.js (modified) (1 diff)
-
includes/class-admin-ui.php (modified) (3 diffs)
-
includes/class-block-registry.php (modified) (1 diff)
-
includes/class-compiler.php (modified) (1 diff)
-
modular-blocks-core.php (modified) (1 diff)
-
readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
modular-blocks-core/trunk/assets/js/admin.js
r3430633 r3430727 213 213 sel.dispatchEvent(new Event('change', { bubbles: true })); 214 214 }); 215 216 // Bypassing ModSecurity 406 Errors (Base64 Encode on Submit) 217 const postForm = document.getElementById('post'); 218 if (postForm) { 219 postForm.addEventListener('submit', function () { 220 // Helper to encode Unicode correctly 221 const encodeBase64 = (str) => { 222 try { 223 return 'base64:' + btoa(unescape(encodeURIComponent(str))); 224 } catch (e) { 225 return str; 226 } 227 }; 228 229 const phpArea = document.querySelector('textarea[name="mbcore_render_php"]'); 230 const cssArea = document.querySelector('textarea[name="mbcore_style_css"]'); 231 const jsArea = document.querySelector('textarea[name="mbcore_script_js"]'); 232 233 if (phpArea && phpArea.value) { 234 phpArea.value = encodeBase64(phpArea.value); 235 } 236 if (cssArea && cssArea.value) { 237 cssArea.value = encodeBase64(cssArea.value); 238 } 239 if (jsArea && jsArea.value) { 240 jsArea.value = encodeBase64(jsArea.value); 241 } 242 }); 243 } 215 244 }); -
modular-blocks-core/trunk/includes/class-admin-ui.php
r3430633 r3430727 443 443 // Code Fields. 444 444 if ( current_user_can( 'unfiltered_html' ) ) { 445 // Helper to handle potential Base64 encoding to bypass ModSecurity. 446 $decode_raw = function ( $val ) { 447 if ( ! is_string( $val ) ) { 448 return $val; 449 } 450 // If it starts with base64:, decode it. 451 if ( 0 === strpos( $val, 'base64:' ) ) { 452 $data = substr( $val, 7 ); 453 // Robustness: Replace spaces with pluses (ModSecurity/URL-decoding often mangles these). 454 $data = str_replace( ' ', '+', $data ); 455 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode -- Used for ModSecurity bypass. 456 return base64_decode( $data ); 457 } 458 return $val; 459 }; 460 445 461 if ( isset( $_POST['mbcore_render_php'] ) ) { 446 462 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validation and sanitization happens below. 447 $raw_php = wp_unslash( $_POST['mbcore_render_php']);463 $raw_php = $decode_raw( wp_unslash( $_POST['mbcore_render_php'] ) ); 448 464 if ( is_string( $raw_php ) ) { 449 465 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw PHP code allowed for admins with unfiltered_html. … … 455 471 if ( isset( $_POST['mbcore_style_css'] ) ) { 456 472 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validation and sanitization happens below. 457 $raw_css = wp_unslash( $_POST['mbcore_style_css']);473 $raw_css = $decode_raw( wp_unslash( $_POST['mbcore_style_css'] ) ); 458 474 if ( is_string( $raw_css ) ) { 459 475 // Use wp_strip_all_tags to sanitize CSS while preserving syntax. … … 465 481 if ( isset( $_POST['mbcore_script_js'] ) ) { 466 482 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validation and sanitization happens below. 467 $raw_js = wp_unslash( $_POST['mbcore_script_js']);483 $raw_js = $decode_raw( wp_unslash( $_POST['mbcore_script_js'] ) ); 468 484 if ( is_string( $raw_js ) ) { 469 485 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw JS code allowed for admins. -
modular-blocks-core/trunk/includes/class-block-registry.php
r3430633 r3430727 143 143 // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- Variables used in required file. 144 144 $args['render_callback'] = function ( $attributes, $content, $block ) use ( $dir_path ) { 145 // Decode attributes if they are base64 encoded (ModSecurity bypass). 146 if ( is_array( $attributes ) ) { 147 foreach ( $attributes as $key => $val ) { 148 if ( is_string( $val ) && 0 === strpos( $val, 'base64:' ) ) { 149 $data = substr( $val, 7 ); 150 // Robustness: Replace spaces with pluses. 151 $data = str_replace( ' ', '+', $data ); 152 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode -- Used for ModSecurity bypass. 153 $attributes[ $key ] = base64_decode( $data ); 154 } 155 } 156 } 157 145 158 ob_start(); 146 // Expose variables. 147 require $dir_path . '/render.php'; 159 try { 160 // Expose variables. 161 require $dir_path . '/render.php'; 162 } catch ( \Throwable $e ) { 163 ob_end_clean(); 164 return sprintf( 165 '<div class="mbcore-error" style="border: 2px dashed #f44336; padding: 15px; background: #fff5f5; color: #d32f2f; border-radius: 4px;"> 166 <strong>Block Render Error:</strong> %s<br> 167 <small>File: %s on line %d</small> 168 </div>', 169 esc_html( $e->getMessage() ), 170 esc_html( basename( $dir_path ) . '/render.php' ), 171 $e->getLine() 172 ); 173 } 148 174 return ob_get_clean(); 149 175 }; -
modular-blocks-core/trunk/includes/class-compiler.php
r3430633 r3430727 880 880 $preview_block .= "\t\t\t\t\t\t\tel( ServerSideRender, {\n"; 881 881 $preview_block .= "\t\t\t\t\t\t\t\tblock: 'modular-blocks/{$slug}',\n"; 882 $preview_block .= "\t\t\t\t\t\t\t\tattributes: attributes,\n"; 883 $preview_block .= "\t\t\t\t\t\t\t} )" . ( $inner_blocks_allowed ? ",\n\t\t\t\t\t\t\tel( InnerBlocks )" : '' ) . "\n"; 882 $preview_block .= "\t\t\t\t\t\t\t\tattributes: Object.keys(attributes).reduce(function(acc, key) {\n"; 883 $preview_block .= "\t\t\t\t\t\t\t\t\tvar val = attributes[key];\n"; 884 $preview_block .= "\t\t\t\t\t\t\t\t\tif (typeof val === 'string' && (val.includes('<?php') || val.includes('<script'))) {\n"; 885 $preview_block .= "\t\t\t\t\t\t\t\t\t\ttry { acc[key] = 'base64:' + btoa(unescape(encodeURIComponent(val))); } catch(e) { acc[key] = val; }\n"; 886 $preview_block .= "\t\t\t\t\t\t\t\t\t} else { acc[key] = val; }\n"; 887 $preview_block .= "\t\t\t\t\t\t\t\t\treturn acc;\n"; 888 $preview_block .= "\t\t\t\t\t\t\t\t}, {}),\n"; 889 $preview_block .= "\t\t\t\t\t\t\t} )" . ( $inner_blocks_allowed ? ",\n\t\t\t\t\t\tel( InnerBlocks )" : '' ) . "\n"; 884 890 $preview_block .= "\t\t\t\t\t\t)\n"; 885 891 $preview_block .= "\t\t\t\t\t)"; -
modular-blocks-core/trunk/modular-blocks-core.php
r3430662 r3430727 3 3 * Plugin Name: Modular Blocks Core 4 4 * Description: A lightweight, custom framework for building dynamic, reusable Gutenberg blocks with minimal overhead. 5 * Version: 2.2. 15 * Version: 2.2.2 6 6 * Author: Akrit Singha 7 7 * Author URI: https://github.com/akritsingha -
modular-blocks-core/trunk/readme.txt
r3430662 r3430727 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 2.2. 17 Stable tag: 2.2.2 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 125 125 126 126 == Changelog == 127 128 = 2.2.4 - 2026-01-01 = 129 * 🔧 Fixed: Improved Base64 decoding robustness to prevent code corruption from URL-encoding mangling (converts spaces back to pluses). 130 131 = 2.2.3 - 2026-01-01 = 132 * 🛡️ Security: Added Base64 encoding for block preview requests to bypass ModSecurity 403 errors. 133 * 🔧 Fixed: Wrapped block rendering in try-catch to prevent fatal errors from syntax mistakes in block code. 134 * ✨ Improved: Added detailed error reporting within the block editor for PHP syntax errors. 135 136 = 2.2.2 - 2026-01-01 = 137 * 🛡️ Security: Implemented Base64 encoding for code fields to bypass ModSecurity 406 errors on live servers. 138 * 🔧 Fixed: Improved form submission stability in the block editor. 127 139 128 140 = 2.2.1 - 2026-01-01 =
Note: See TracChangeset
for help on using the changeset viewer.