Security

  • JNext lesson
  • KPrevious lesson
  • FSearch lessons
  • EscClear search

The plugin implements multiple layers of security to protect against unauthorized access and malicious content.

Authentication and Authorization

Builder Access

Every visual builder request is validated with three checks.

  1. Authentication. The user must be logged in to WordPress.
  2. Nonce verification. The pb_nonce parameter must be a valid WordPress nonce for the specific post ID. Nonces are generated per-post using the action string md_page_blocks_builder_{post_id}.
  3. Capability check. The user must have the edit_post capability for the target post.

If any check fails, the builder returns a 403 Forbidden response with a “You do not have permission” message.

AJAX Endpoints

Both AJAX endpoints (md_page_blocks_builder_apply and md_page_blocks_builder_preview) perform the same three checks: authentication, nonce verification, and capability check.

The apply endpoint uses the builder nonce. The preview endpoint accepts either the preview nonce or the builder nonce (since preview can be triggered from both the Gutenberg editor and the visual builder, which use different nonces).

Both endpoints are registered as authenticated-only (wp_ajax_ hooks). Unauthenticated requests never reach the handlers.

Post Type Restrictions

Even with valid authentication and nonce, the builder checks that the target post’s post type is in the allowed list (configured in plugin settings or via the md_page_blocks_builder_post_types filter).

CSS Sanitization

All CSS output is sanitized to prevent XSS vectors. The sanitization runs on every block render and removes.

  • javascript: protocol references.
  • expression() function calls (used in older IE for script injection).
  • -moz-binding: declarations (Firefox XBL binding, a historical attack vector).
  • behavior: declarations (IE HTC behavior, another historical attack vector).
  • @import url() with javascript: or data: protocols.
  • url() with data:text/html content (used for HTML injection).

CSS is also stripped of all HTML tags via wp_strip_all_tags before these replacements.

Content Minification

All output (HTML, CSS, JavaScript) is minified before rendering. While primarily a performance optimization, minification also removes comments that could leak implementation details.

CSS Minification

  • Removes CSS comments.
  • Strips whitespace, newlines, and tabs.
  • Collapses multiple spaces.
  • Removes spaces around structural characters ({}:;,>~+).
  • Removes trailing semicolons before closing braces.

JavaScript Minification

  • Removes block comments (but preserves /*! license comments).
  • Removes line comments.
  • Collapses whitespace.
  • Removes spaces around structural characters.

HTML Minification

  • Preserves content inside <pre>, <code>, <script>, <style>, and <textarea> tags.
  • Removes HTML comments (except IE conditional comments).
  • Collapses whitespace between tags to a single space.
  • Collapses runs of whitespace.

PHP Execution Security

PHP execution is gated by a permission check that defaults to requiring manage_options capability (administrators) for preview contexts. On the frontend, PHP executes for all visitors because the code has already been reviewed and saved by an administrator.

The gt_page_blocks_can_execute_php filter allows you to implement stricter controls. See the PHP Execution chapter for details.

When PHP execution is denied, PHP tags are stripped from the content rather than rendered as visible code.

Preview Iframe Sandboxing

The visual builder’s preview iframe uses the sandbox attribute with allow-scripts allow-same-origin. This means.

  • Scripts in the preview can run (needed for JavaScript preview).
  • The preview can access same-origin resources (needed for theme assets).
  • The preview cannot navigate the top-level page.
  • The preview cannot create popups.
  • The preview cannot submit forms (to the parent context).

The Gutenberg block editor’s preview iframe uses a more restrictive sandbox="allow-scripts" (without allow-same-origin).

Nonce Generation

The plugin uses two separate nonce actions.

  • Builder nonce: md_page_blocks_builder_{post_id} for builder access and the apply endpoint.
  • Preview nonce: md_page_blocks_preview_{post_id} for the preview endpoint.

The preview endpoint accepts both nonce types for compatibility, since previews can be triggered from the Gutenberg editor (which uses the preview nonce) or from within the visual builder (which uses the builder nonce).

Input Sanitization

All input from requests is sanitized.

  • Post IDs are cast to integers via absint().
  • Nonces are passed through sanitize_text_field().
  • Section data is JSON-decoded and then normalized through normalize_builder_section(), which casts all fields to their expected types.
  • Post type slugs are sanitized with sanitize_key().
  • Template slugs are sanitized with sanitize_file_name().

License Server Communication

License verification requests are made over HTTPS to the license server. The plugin sends the license key (or activation hash for subsequent checks), the site URL, and the current plugin version. No other site data is transmitted.