WP Manifestindependent plugin directory
manifest / integrations / wp-graphql-gutenberg

WP GraphQL Gutenberg WP Registry grade D+. High-severity findings · 3 findingsWP RegistryHigh-severity findings · 3 findingsOpen the reportD+

Query gutenberg blocks with wp-graphql

★ 305stars
116kcomposer installs
v0.4.1latest · 3 years ago

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/pristas-peter/wp-graphql-gutenberg/archive/refs/heads/develop.zip

On Packagist as pristas-peter/wp-graphql-gutenberg:

composer require pristas-peter/wp-graphql-gutenberg
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

Query gutenberg blocks through wp-graphql

Install

  • Requires PHP 7.0+
  • Requires wp-graphql 0.9.0+
  • Requires WordPress 5.4+

Quick Install

Download and install like any WordPress plugin. Details here.

Releases

22 releases.

Tag
Published
v0.4.1 latest
Dec 5, 2022 3 years ago
Dec 2, 2022 3 years ago
May 19, 2022 4 years ago
Aug 16, 2021 5 years ago
Aug 6, 2021 5 years ago
Aug 6, 2021 5 years ago
Mar 5, 2021 5 years ago
Jan 18, 2021 5 years ago
Dec 10, 2020 5 years ago
Nov 21, 2020 5 years ago
Jun 25, 2020 6 years ago
Jun 16, 2020 6 years ago
Jun 12, 2020 6 years ago
Jun 2, 2020 6 years ago
May 28, 2020 6 years ago
May 21, 2020 6 years ago
May 11, 2020 6 years ago
Apr 30, 2020 6 years ago
Jan 8, 2020 6 years ago
Dec 5, 2019 6 years ago
Dec 2, 2019 6 years ago
Oct 30, 2019 6 years ago

These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.

D+ grade

Security

WP GraphQL Gutenberg 0.4.1 · audited by WP Registry

High-severity findings.

1 high 2 medium
Audited release
0.4.1
Findings
3
Worst severity
high
Content hash
e0a1bbbe82d8a1f000a0fa41…

Findings

  • high core/block ref loads arbitrary post_content into public GraphQL innerBlocks without capability or status checks

    information_disclosure

    When resolving Gutenberg blocks, Block::__construct treats a core/block node's attrs.ref as a reusable-block ID and replaces innerBlocks with parse_blocks(get_post($ref)->post_content). get_post() is not limited to post_type wp_block, and there is no check of post_status, post_password, or current_user_can('read_post'). WordPress core's render_block_core_block() refuses anything that is not a published, non-password wp_block; this plugin does not. The blocks / blocksJSON fields on BlockEditorContentNode (and Block.innerBlocks) are public GraphQL reads on any post WPGraphQL already exposes. An Author (publish_posts) can publish <!-- wp:block {"ref":<id>} /--> pointing at another user's draft, a private page, a password-protected post, or an unused reusable block; unauthenticated clients can then query that published post's blocks { innerBlocks { originalContent saveContent attributesJSON } } and receive the hidden post_content. A Contributor can do the same against their own draft via authenticated GraphQL. The sibling reusableBlock field correctly goes through WPGraphQL's post resolver (capability-aware); the innerBlocks expansion bypasses that model layer entirely.

    src/Blocks/Block.php:189-196

    Recommendation

    Mirror render_block_core_block: require the ref to be post_type wp_block, post_status publish, and empty post_password before expanding innerBlocks. For non-public refs, still require current_user_can('read_post', $id) (or go through WPGraphQL's DataSource::resolve_post_object and skip expansion on failure). Do not call get_post() on arbitrary IDs from block attributes without those checks.

  • medium Contributor+ can overwrite the site-wide GraphQL block registry via the preview batch REST route

    missing_capability

    POST /wp-json/wp-graphql-gutenberg/v1/block-editor-previews/batch is gated only on current_user_can('edit_posts') (wgg_preview uses default capability_type 'post'). The callback's first statement is Registry::update_registry(Registry::normalize($request->get_param('block_types'))), which update_option('wp_graphql_gutenberg_block_types', $registry). The dedicated /block-registry route correctly requires edit_others_posts, but the batch route duplicates that write with a weaker cap. src/PostTypes/block-editor-preview/index.js always sends getBlockRegistry() when anyone with the block editor open saves previews, so a Contributor merely editing a draft overwrites the option. That option is the source of truth for GraphQL type registration (BlockTypes.php) and for CSS-selector attribute sourcing (Block::source_attributes) on every subsequent public GraphQL request. Attacker-supplied block names/attributes can break schema generation (DoS of /graphql for headless frontends), collide with types such as Block (format_block_name('block') => 'Block'), or install hostile selectors/pattern regexes used when parsing other posts' HTML. Subscriber/customer/unauth are blocked by the permission_callback; REST cookie auth still requires the WP nonce.

    src/PostTypes/BlockEditorPreview.php:203-208

    Recommendation

    Do not update wp_graphql_gutenberg_block_types from the preview batch endpoint. Keep registry writes on /block-registry with a manage_options (or at least edit_others_posts) permission_callback, and validate/sanitize block type names and attribute schemas before storing. If batch must refresh the registry, require the same capability as /block-registry and reject empty/malformed block_types.

  • medium Block-editor previews lack object-level authorization on write and GraphQL read

    missing_capability

    insert_preview() creates or updates wgg_preview auto-drafts from client-supplied post_id / preview_post_id / post_content with no current_user_can('edit_post', $post_id) check. The batch REST handler iterates attacker-controlled batch keys as those IDs and, if a preview already exists, sets insert_options['ID'] and calls wp_insert_post (which does not enforce caps). A Contributor can therefore overwrite another user's unpublished preview. On the read side, GraphQL previewBlocks / previewBlocksJSON wrap the resolver in Utils::ensure_capability(..., fn($cap) => $cap->edit_posts), which only tests the primitive 'edit_posts' capability — not edit_post on the parent, not edit_post on the preview. Because the parent post can be a published post the Contributor is allowed to query, they receive that post's unpublished preview tree (the other editor's in-progress blocks). The connection filter graphql_post_object_connection_query_args similarly forces post_status=auto-draft for anyone with edit_posts on wgg_preview.

    src/PostTypes/BlockEditorPreview.php:64-92

    Recommendation

    Before insert/update, require current_user_can('edit_post', $post_id) (and the same for $preview_post_id). When updating an existing preview, also require current_user_can('edit_post', $preview_id). For GraphQL previewBlocks/previewBlocksJSON and the auto-draft connection, require object-level edit_post on the previewed post (or restrict to the current user's previews) instead of the primitive edit_posts capability.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.