A mutação `sendPasswordResetEmail` no WPGraphQL é projetada explicitamente para evitar a enumeração do usuário. O resolvedor em `src/Mutation/EnviarPasswordResetEmail.php` declara em um comentário de código: `// Nós obsfuscamos o sucesso real desta mutação para evitar a enumeração do usuário.` A mutação sempre retorna `sucesso: true`, independentemente de o nome de usuário/e- mail fornecido pertencer a um usuário existente. O campo de saída público pretendido é apenas `sucesso: Boolean`.
No entanto, um campo de ` user` deprecado ainda está registrado no tipo de saída `EnviarPasswordResetEmailPayload` no `src/Deprecated.php` (linhas 433 - 450 ). Este campo depreciado resolve- se para um objeto completo `Usuário` quando o nome de usuário/ e- mail fornecido corresponde a um usuário existente da classe de autor, e `null` de outra forma — minando completamente o projeto anti- enumeração. O `@ todo remover em 3.0.0 ` comentário reconhece que o campo está programado para remoção, mas permanece ativo em todos 2 Lançamentos do.x, incluindo atual 2.14.1. Descoberto através da revisão de código fonte em Maio 29, 2026.
O resolvedor de mutações em `src/Mutation/SendPasswordResetEmail.php`. ``` php $payload = ['sucesso' => true, 'id' => null]; $user_data = self::get_user_data($input['username']); se (!$user_data) { graphql_debug((...); devolver $payload; // id permanece null } //...enviar e-mail, então... devolver ['id' => $user_data-> ID, 'sucesso' => true]; ```` O campo de saída pública pretendido é apenas "sucesso". O `id` é estado somente interno para os resolvedores a jusante. `src/Deprecated.php` registra um campo adicional `user` no mesmo tipo de carga útil. ```php register_graphql_field( 'EnviarPasswordResetEmailPayload', 'usuário', [ 'tipo' => 'Usuário', 'deprecationReason' => função estática () { devolver __('Este campo será removido...'); }, 'resolver' => função estática ($payload, $args, AppContext $context) { devolver!vacuidade($payload['id'])? $context->get_loader('user')->load_deferred($payload['id']): null; }, ], );.
Este campo lê o `$payload['id']' interno e o resolve através do carregador padrão do usuário. A política do Modelo do Usuário `permitido_restrito_campos` permite ler sem autênticas campos de autores públicos (`databaseId`, `name`, `firstName`, `lastName', `slug', `descrição', `uri', `url`). ``` graphql mutation EnumerateUser { sendPasswordResetEmail(input: { nome de usuário: "victim@example.com" }) { sucesso usuário { databaseId nome firstName lastName slug description uri } } } ``` Comportamento: - Utilizador/email não existente → `data.sendPasswordResetEmail.user` é `null` - - Utilizador existente da classe autor → `data.sendPasswordResetEmail.user` é um objeto de usuário completo com os campos listados povoados - - `sucesso` sempre retorna `verdadeiro`, preservando a aparência de obfuscação — o campo `usuário` depreciado é o vazamento ## Impacto.
1 ** Nome de usuário/email enumeração:** o atacante não autêntico pode verificar se algum nome de usuário ou e-mail está registrado, sem limitação de taxa do lado do WPGraphQL 2. 2 **Disclosão do perfil para usuários da classe de autores:** para qualquer usuário com postagens publicadas (incluindo editores e administradores), o atacante obtém `databaseId`, `name', `firstName', `lastName', `slug', `descrição' (biologia do usuário), `uri' — substancialmente mais do que mera existência 3. 3 **Apassa endurecimento parcial:** sites que desativaram o endpoint do usuário da API REST, o mapa do site XML do usuário e os redirecionamentos do autor `?author=N` podem ainda estar vulneráveis através deste caminho do WPGraphQL 4. 4 ** Configuração de dispersão:** primeiroNome/últimoNome/descrição para autores fornece material de phishing personalizado ## Resolução recomendada Remover completamente o campo ` usuário ' depreciado (avançar o `@ todo remove existente em 3.0.0 `) ou mudar o resolvedor para sempre devolver `null`:.
```diff 'resolver' => função estática ($payload, $args, AppContext $context) { - devolver!vazio($payload['id'))? $context->get_loader('user')->load_deferred($payload['id']): null; - + // Sempre null — este campo despreciado já vazou a existência do usuário, - +// prejudicando o design anti-enumeração da mutação sendPasswordResetEmail. - + devolver null; - }, - ```' Defesa em profundidade — mude o próprio resolvedor de mutação para não popular `$payload['id']' no verdadeiro sucesso: ````diff retorno [ - 'id' => $user_data-> ID, - + 'id' => null, - 'sucesso' => true, - ]; - ```.
Luke Granto — pesquisador independente de segurança que opera de boa fé. Descoberta via revisão de código fonte do wp-graphql/wp-graphql v 2.14.1, aproximadamente 15 minutos desde o 'git clone' até o erro confirmado. Nenhuma exploração ao vivo contra qualquer implantação de terceiros. Registro de aconselhamento: GHSA-jhh 7 - 832 h- f 8 HV. Identificadores relacionados: CVE- 2026 - 54768.
Tempo: GitHub Advisory Database publicou este registro em 2026 - 07 - 31 T 22: 24: 29.000 Z e lista a sua última modificação como 2026 - 07 - 31 T 22: 24: 29.000 Z. Gravidade: MODERAR. Dados de pontuação publicados: CVSS_V 4: CVSS: 4.0 /AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/África do Sul:N.
Software afetado e informações de versão: pacote Packagist wp-graphql/wp-graphql — ECOSISTEM: introduzido 0, última afetada 2.6.0. Classificação e evidência: identificadores de fraqueza CWE- 204. O registro contém 3 suporte de referências nestes tipos: WEB, PACKAGE.