Riscos do código de plugins WordPress gerado por IA
O uso de modelos de linguagem grandes (LLMs) como GPT-4, Claude 3.5 Sonnet ou Gemini Pro para escrever código de plugins de WordPress tornou-se uma prática comum para programadores e proprietários de sites. A promessa é extremamente atraente: descreva a funcionalidade necessária em linguagem natural e a IA gerará um ficheiro PHP pronto a usar em questão de segundos.
O problema, no entanto, é que os modelos de linguagem destacam-se em sintaxe e estrutura, mas carecem de contexto operacional e de uma compreensão real dos princípios de segurança dentro do ecossistema do WordPress. Treinados em bases de dados massivas de código público, herdam milhões de plugins obsoletos, inseguros e mal escritos publicados durante as últimas duas décadas. Como resultado, a IA produz frequentemente código sintaticamente impecável e funcional, mas repleto de vulnerabilidades de segurança críticas sob o capô.
Como engenheiros de WordPress, devemos adotar uma postura estrita de “Zero Trust” em relação a qualquer código escrito por uma IA. Este guia analisa os cinco padrões de falhas de segurança mais comuns que observamos durante as auditorias de código de plugins gerados por IA, ilustrando-os com fragmentos de PHP vulneráveis junto com refatorizações seguras e de nível de produção que cumprem com os Padrões de Codificação do WordPress (WPCS).
1. Uso incorreto de is_admin() para o controlo de acesso
Talvez o erro lógico mais comum que a IA comete ao tentar proteger um endpoint seja confiar na função is_admin() para restringir o acesso aos administradores.
Porque é que is_admin() não verifica permissões
Apesar do seu nome, is_admin() não verifica se o utilizador atualmente ligado é um administrador. Apenas comprova se o pedido atual é para uma página de administração (como qualquer URL que comece com /wp-admin/).
Cada pedido AJAX enviado a /wp-admin/admin-ajax.php, seja iniciado por um administrador, um subscritor ligado com capacidades mínimas ou um visitante anónimo não autenticado, fará com que is_admin() devolva true.
is_admin() como única verificação ao guardar
// Um gancho gerado por IA para guardar a configuração do plugin
add_action( 'admin_init', 'ai_save_plugin_settings' );
function ai_save_plugin_settings() {
// A IA assume incorretamente que isto restringe o acesso aos administradores
if ( is_admin() ) {
if ( isset( $_POST['my_plugin_option'] ) ) {
update_option( 'my_plugin_option', $_POST['my_plugin_option'] );
}
}
}Verificar permissões com current_user_can()
Para verificar as permissões reais do utilizador ligado, deve usar a função current_user_can(), passando uma capacidade de utilizador específica em vez de um nome de perfil, como manage_options.
add_action( 'admin_init', 'secure_save_plugin_settings' );
function secure_save_plugin_settings() {
// 1. Verificar as capacidades reais do utilizador atual
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Não tem permissão para executar esta ação.', 'secure-plugin' ) );
}
if ( isset( $_POST['my_plugin_option'] ) ) {
// Aplicar sanitização de entrada (ver Secção 4)
$sanitized_value = sanitize_text_field( wp_unslash( $_POST['my_plugin_option'] ) );
update_option( 'my_plugin_option', $sanitized_value );
}
}2. Como verificar o nonce no WordPress contra CSRF
Os ataques de falsificação de solicitação em sites cruzados (CSRF) enganam o navegador de um utilizador autenticado (por exemplo, um administrador) para executar ações não autorizadas num site em que iniciou sessão. O WordPress utiliza tokens criptográficos chamados nonces para proteger contra CSRF.
Os geradores de IA frequentemente omitem a criação e verificação de nonces em formulários de administração, manipuladores AJAX e endpoints de API REST personalizados. Isto ocorre porque a implementação de nonces requer coordenar a camada de renderização frontend (o formulário HTML que contém o campo nonce) com o controlador de processamento backend, o que é difícil de alinhar para os LLMs através de gerações de código desconetadas.
Manipulador AJAX sem verificação de nonce
// Registo de endpoint AJAX gerado por IA
add_action( 'wp_ajax_ai_delete_post', 'ai_delete_post_handler' );
function ai_delete_post_handler() {
// A IA comprova as capacidades mas ignora por completo CSRF (sem verificação de nonce)
if ( ! current_user_can( 'delete_posts' ) ) {
wp_send_json_error( 'Não autorizado.' );
}
$post_id = intval( $_POST['post_id'] );
wp_delete_post( $post_id );
wp_send_json_success( 'Artigo eliminado.' );
}Verificar o nonce com check_ajax_referer()
O formulário de saída deve gerar um campo nonce usando wp_nonce_field(), e o controlador PHP recetor deve verificar o token usando check_ajax_referer() or wp_verify_nonce().
// No ficheiro de renderização do formulário ou payload de javascript:
// wp_nonce_field( 'delete_post_action', 'my_nonce_field' );
// Registo do manipulador AJAX seguro
add_action( 'wp_ajax_secure_delete_post', 'secure_delete_post_handler' );
function secure_delete_post_handler() {
// 1. Verificar o token CSRF cedo
check_ajax_referer( 'delete_post_action', 'my_nonce_field' );
// 2. Verificar as capacidades do utilizador
if ( ! current_user_can( 'delete_posts' ) ) {
wp_send_json_error( 'Não autorizado.' );
}
// 3. Validar e tipar as variáveis de entrada
if ( ! isset( $_POST['post_id'] ) ) {
wp_send_json_error( 'Falta o ID do artigo.' );
}
$post_id = absint( $_POST['post_id'] );
if ( wp_delete_post( $post_id ) ) {
wp_send_json_success( 'Artigo eliminado com sucesso.' );
} else {
wp_send_json_error( 'Erro ao eliminar o artigo.' );
}
}Contra o que um nonce do WordPress não protege
Um nonce prova apenas que o pedido veio de um formulário ou ligação que o WordPress gerou para este utilizador. O capítulo sobre nonces das APIs de segurança do WordPress diz que nunca se deve confiar em nonces para autenticação, autorização ou controlo de acesso, e é por isso que a verificação de capacidades continua obrigatória ao lado dele. Na revisão contam três propriedades. O nonce é gerado por utilizador e por sessão, por isso um token copiado de uma conta falha noutra. A duração predefinida é de 24 horas, dividida em dois períodos (ticks), e o WordPress aceita o período atual e o anterior, pelo que um token concreto funciona entre 12 e 24 horas. Além disso, um nonce não é de utilização única: o mesmo valor pode ser enviado de novo dentro dessa janela, por isso não trava a repetição de pedidos (replay). Um manipulador gerado que trata um nonce válido como prova de identidade tem proteção contra CSRF e, mesmo assim, nenhum controlo de acesso.
3. Vulnerabilidades de injeção SQL em consultas $wpdb
Quando um plugin interage diretamente com a base de dados em vez de utilizar o wrapper nativo WP_Query, utiliza o objeto global $wpdb. Infelizmente, os LLMs com frequência constroem strings SQL sem processar utilizando a concatenação direta de variáveis fornecidas pelo utilizador ($_POST, $_GET) em vez de parametrizar a consulta.
Porque é que concatenar SQL é perigoso
Concatenar variáveis sem processar diretamente nas consultas da base de dados permite a um atacante manipular a estrutura da consulta. Isto pode levar à recuperação não autorizada de dados (como senhas de utilizador hash), à eliminação da base de dados ou à escalação de privilégios administrativos.
Consulta SQL com variável concatenada
// Função de pesquisa de utilizadores gerada por IA
function ai_find_users_by_city( $city_name ) {
global $wpdb;
// Falha crítica: concatenação direta da variável de consulta
$query = "SELECT * FROM {$wpdb->prefix}custom_users WHERE city = '" . $city_name . "'";
return $wpdb->get_results( $query );
}Proteger consultas com $wpdb->prepare()
Nunca se devem escrever variáveis sem processar diretamente nas strings SQL. Em seu lugar, utilize o método $wpdb->prepare(), que funciona como um motor de consultas parametrizadas, tipando e escapando os valores através de especificadores de formato (%s para strings, %d para inteiros, %f para decimais).
function secure_find_users_by_city( $city_name ) {
global $wpdb;
// 1. Usar prepare() com especificadores de formato
$query = $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}custom_users WHERE city = %s",
$city_name
);
return $wpdb->get_results( $query );
}Nota: Se a variável $city_name provém diretamente da entrada do utilizador, ainda deve ser sanitizada usando sanitize_text_field() antes do processamento da base de dados.
4. Sanitizar e escapar dados no WordPress (XSS)
Cross-Site Scripting (XSS) é uma das vulnerabilidades mais comuns encontradas nos plugins de WordPress. Permite que o código JavaScript malicioso seja armazenado na base de dados ou seja refletido dinamicamente, executando-se nos navegadores de visitantes desprevenidos.
Os modelos de IA frequentemente confundem a sanitização (limpeza de dados ao entrar) com o escape (asseguramento de dados ao sair). Mesmo se a IA sanitiza as entradas, frequentemente exibe variáveis nos modelos sem as escapar primeiro, deixando o site exposto a XSS armazenado.
Saída de dados sem escape
// Ciclo de exibição de comentários escrito por IA
function ai_display_user_feedback() {
$feedbacks = get_option( 'ai_user_feedback_list', [] );
echo '<div class="feedback-list">';
foreach ( $feedbacks as $feedback ) {
// Falha crítica: saída sem processar e sem escapar
echo '<p class="feedback-item">' . $feedback['user_comment'] . '</p>';
}
echo '</div>';
}Escapar a saída com esc_html()
Siga a regra fundamental do WordPress: Sanitize Early, Escape Late (sanitize as variáveis de entrada imediatamente; escape a saída imediatamente antes de a enviar para o navegador).
Escolha a função de escape correta para o contexto:
esc_html()- para nós de texto padrão dentro de elementos HTML.esc_attr()- para a saída dentro de valores de atributos HTML.esc_url()- para a saída de ligações.wp_kses()- quando deva permitir tags HTML específicas e seguras (como strong, anchors).
function secure_display_user_feedback() {
$feedbacks = get_option( 'secure_user_feedback_list', [] );
echo '<div class="feedback-list">';
foreach ( $feedbacks as $feedback ) {
$comment = isset( $feedback['user_comment'] ) ? $feedback['user_comment'] : '';
// 1. Escapar a saída contextualmente imediatamente antes de renderizar
echo '<p class="feedback-item">';
echo esc_html( $comment );
echo '</p>';
}
echo '</div>';
}5. Carregamento seguro de ficheiros no WordPress
Permitir aos utilizadores carregar ficheiros (como anexos de formulários de contacto ou carregamento de avatares) é uma das operações de maior risco num site. Um erro aqui permite aos atacantes carregar um ficheiro .php, o que resulta na Execução Remota de Código (RCE) e no comprometimento total do servidor.
Os manipuladores de ficheiros gerados por IA frequentemente dependem de comandos nativos do PHP como move_uploaded_file() combinados com verificações fracas de extensão de ficheiro (como uma simples correspondência de strings), que são triviais de contornar para os atacantes (por exemplo, carregar ficheiros chamados malicious.php.jpg ou usar extensões alternativas como .phtml).
Carregamento com move_uploaded_file() e verificação de extensão
// Manipulador de carregamento escrito por IA
function ai_handle_avatar_upload() {
if ( isset( $_FILES['avatar'] ) ) {
$file_name = $_FILES['avatar']['name'];
$ext = pathinfo( $file_name, PATHINFO_EXTENSION );
// A IA assume que esta verificação de extensão é segura
if ( in_array( $ext, ['jpg', 'jpeg', 'png'] ) ) {
$target = wp_upload_dir()['path'] . '/' . $file_name;
move_uploaded_file( $_FILES['avatar']['tmp_name'], $target );
}
}
}Carregamento seguro com wp_handle_upload()
Nunca use move_uploaded_file() nativo do PHP dentro do WordPress. Em seu lugar, utilize a função core wp_handle_upload(). Realiza uma verificação robusta do tipo MIME (verificando a assinatura real do ficheiro, não apenas o seu nome), valida o estado do carregamento e integra-se no sistema de permissões do WordPress.
function secure_handle_avatar_upload() {
// 1. Validar o token CSRF
if ( ! isset( $_POST['avatar_upload_nonce'] ) || ! wp_verify_nonce( $_POST['avatar_upload_nonce'], 'upload_avatar_action' ) ) {
wp_die( esc_html__( 'Token de segurança não válido.', 'secure-plugin' ) );
}
// 2. Verificar as verificações de capacidades
if ( ! current_user_can( 'upload_files' ) ) {
wp_die( esc_html__( 'Não tem permissão para carregar ficheiros.', 'secure-plugin' ) );
}
if ( isset( $_FILES['avatar'] ) ) {
if ( ! function_exists( 'wp_handle_upload' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
// 3. Restringir à força os tipos MIME permitidos
$allowed_mimes = [
'jpg|jpeg' => 'image/jpeg',
'png' => 'image/png'
];
$upload_overrides = [
'test_form' => false,
'mimes' => $allowed_mimes
];
// 4. Delegar o processamento do carregamento à função core
$movefile = wp_handle_upload( $_FILES['avatar'], $upload_overrides );
if ( $movefile && ! isset( $movefile['error'] ) ) {
$avatar_url = $movefile['url'];
update_user_meta( get_current_user_id(), 'user_avatar', $avatar_url );
} else {
// Registar a falha de forma segura
error_log( 'Falha no carregamento de ficheiros: ' . $movefile['error'] );
}
}
}6. Funções do WordPress inventadas e pacotes Composer falsos
Há uma classe de erro exclusiva dos modelos generativos: inventar com toda a confiança código que não existe. Como um LLM prevê tokens plausíveis em vez de consultar a referência real do WordPress, chama sem hesitar funções que nunca fizeram parte do núcleo, como wp_verify_admin(), get_current_user_role() ou sanitize_all_input(). Estes nomes parecem credíveis porque seguem as convenções de nomes do WordPress, e muitas vezes o primeiro sinal é um erro fatal em execução. Pior ainda: um programador com pressa “corrige” o erro fatal escrevendo o seu próprio invólucro mínimo com o nome inventado e reintroduz exatamente a falha de sanitização ou de permissões que a função inventada prometia fechar.
O mesmo padrão afeta as dependências de terceiros. Quando a IA gera um composer.json ou sugere linhas require, pode indicar pacotes que não existem no Packagist ou, pior, pacotes cujo nome difere num único carácter de uma biblioteca legítima. Os atacantes exploram este “slopsquatting” registando antecipadamente os nomes alucinados, de modo que um composer install sem revisão põe código malicioso diretamente no plugin.
Duas verificações concretas fecham esta falha. Primeiro, confirme cada função desconhecida na referência oficial de código do WordPress antes de confiar nela; se não existir entrada, trate a chamada como inventada. Segundo, fixe e reveja cada dependência: verifique que o pacote existe exatamente com esse nome, que vem do responsável esperado e que está fixado numa versão revista em vez de num intervalo aberto.
// Alucinada: esta função não existe no núcleo
if ( wp_current_user_is_admin() ) { /* ... */ }
// API real do WordPress
if ( current_user_can( 'manage_options' ) ) { /* ... */ }wp plugin verify-checksums compara os ficheiros do plugin com as somas de verificação publicadas no WordPress.org (documentação do WP-CLI), por isso só ajuda em plugins do diretório, não num plugin escrito pela IA. Para as dependências Composer, o controlo é um composer.lock fixado e revisto no diff, e composer why <pacote> mostra que requisito trouxe um pacote inesperado.
7. Como bloquear o acesso direto aos ficheiros PHP do plugin
Cada ficheiro PHP de um plugin ou tema deve recusar-se a executar se o WordPress não tiver sido carregado. O manual de plugins recomenda para isso verificar a constante ABSPATH no início do ficheiro. O código gerado omite muitas vezes essa linha, sobretudo em ficheiros auxiliares que o modelo separou para tornar o código mais legível.
Ficheiro auxiliar sem verificação de ABSPATH
<?php
function fjord_get_export_rows() {
global $wpdb;
return $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}fjord_records" );
}Um pedido direto a /wp-content/plugins/fjord-exporter/helpers.php pode executar o ficheiro fora do WordPress e, consoante a configuração do servidor, contornar por completo o início de sessão.
Verificação de ABSPATH nos ficheiros PHP do plugin
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}Na revisão, a regra é simples: cada ficheiro .php na pasta do plugin precisa destas linhas, incluindo uninstall.php e cópias de bibliotecas. Também são suspeitos os ficheiros “API” gerados que carregam o WordPress por conta própria com require 'wp-load.php'; e depois não verificam a autenticação.
8. Rotas da REST API sem permission_callback
Os plugins gerados expõem dados muitas vezes através de register_rest_route() em vez de admin-ajax.php. A decisão de acesso de uma rota REST está num único argumento, permission_callback, e os modelos erram de duas formas: omitem-no ou definem-no como __return_true para fazer desaparecer um erro 401 durante os testes.
O manual da REST API cobre os dois casos. Desde o WordPress 5.5, uma rota registada sem permission_callback gera um aviso _doing_it_wrong com o nome da rota, por isso o callback em falta aparece no registo de depuração de qualquer site com WP_DEBUG ativo. __return_true é o valor documentado para endpoints que devem ser públicos. Com ele não surge nenhum aviso, de modo que uma rota de escrita marcada como pública por engano passa despercebida.
Rota de escrita aberta a qualquer pessoa
register_rest_route( 'fjord/v1', '/settings', array(
'methods' => 'POST',
'callback' => 'fjord_update_settings',
'permission_callback' => '__return_true',
) );Rota de escrita com verificação de capacidades e argumentos validados
register_rest_route( 'fjord/v1', '/settings', array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => 'fjord_update_settings',
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
'args' => array(
'label' => array(
'type' => 'string',
'required' => true,
'validate_callback' => function ( $value ) {
return is_string( $value ) && strlen( $value ) <= 100;
},
'sanitize_callback' => 'sanitize_text_field',
),
),
) );Para cada argumento, validate_callback devolve true ou false e o servidor REST rejeita dados inválidos com um erro que o cliente consegue ler, enquanto sanitize_callback limpa o valor antes de chegar ao seu callback. Na revisão, liste cada chamada a register_rest_route() e leia primeiro o respetivo permission_callback: um __return_true numa rota que aceita mais do que GET precisa de uma justificação escrita. Para pedidos do navegador autenticados por cookie, o capítulo sobre autenticação acrescenta outra regra: sem um nonce wp_rest no cabeçalho X-WP-Nonce, a API define o utilizador atual como 0. Um script de frontend que só “funciona” porque salta o nonce está, na prática, a chamar a rota como um visitante sem sessão iniciada.
Como auditar código de plugins WordPress gerado por IA
Para implementar de forma segura o código gerado por IA, a sua equipa de engenharia deve estabelecer um processo de revisão sistemático. Implemente estes três passos antes de enviar qualquer ativo gerado para produção:
Passo 1: Automatizar a análise estática (PHPCS)
Configure os Padrões de Codificação do WordPress (WPCS) para a ferramenta PHP_CodeSniffer. Escaneia ficheiros e identifica automaticamente a falta de sanitização, os nonces omitidos e as variáveis sem escapar.
# Escanear um ficheiro de plugin gerado usando os padrões do WordPress
vendor/bin/phpcs --standard=WordPress-Extra path/to/generated-plugin.phpQue regras do WPCS detetam estas falhas de segurança
O WordPress Coding Standards 3.x só se instala via Composer e precisa de PHP 7.2 ou superior; o repositório do WordPressCS publicou a versão 3.4.1 em julho de 2026.
composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
composer require --dev wp-coding-standards/wpcs:"^3.0"WordPress-Extra contém WordPress-Core mais práticas recomendadas. As regras (sniffs) de segurança estão em dois grupos. WordPress.Security.NonceVerification assinala leituras de $_POST e $_GET sem verificação prévia de nonce, WordPress.Security.ValidatedSanitizedInput assinala variáveis superglobais usadas sem isset(), wp_unslash() e uma função de sanitização, WordPress.Security.EscapeOutput assinala saída sem escape e WordPress.Security.SafeRedirect assinala wp_redirect() onde deveria haver um redirecionamento seguro. Do lado da base de dados, WordPress.DB.PreparedSQL e WordPress.DB.PreparedSQLPlaceholders assinalam SQL com variáveis interpoladas e erros de marcadores, e WordPress.DB.DirectDatabaseQuery marca as consultas diretas para revisão. Assim executa apenas as regras de segurança sobre um plugin gerado:
vendor/bin/phpcs --standard=WordPress --sniffs=WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput,WordPress.Security.EscapeOutput,WordPress.DB.PreparedSQL path/to/generated-plugin/Nenhuma regra sabe se um manipulador exige a capacidade certa, por isso a revisão de current_user_can() no passo 2 continua manual.
Passo 2: Realizar uma revisão de código manual
Revisa cada manipulador que execute consultas HTTP, transações de base de dados, chamadas AJAX ou ligações de API REST segundo o seguinte diagrama de fluxo:
graph TD
A["Receber Código de Plugin Escrito por IA"] --> B{"Aceita entrada do utilizador?"}
B -- Sim --> C["Verificar nonce e capabilities"]
B -- Não --> D{"Modifica a base de dados?"}
C --> C1["Implementar check_ajax_referer() / validação CSRF"]
C --> C2["Implementar current_user_can() verificação de permissões"]
C1 --> D
C2 --> D
D -- Sim --> E["Verificar uso de $wpdb->prepare()"]
D -- Não --> F{"Envia saída para o navegador?"}
E --> E1["Implementar variáveis SQL parametrizadas"]
E1 --> F
F -- Sim --> G["Verificar esc_html(), esc_attr(), ou esc_url()"]
F -- Não --> H["Proceder aos testes de integração"]
G --> G1["Implementar escape de saída contextual"]
G1 --> HPasso 3: Executar testes com privilégios baixos
Verifique os limites de acesso do código. Inicie sessão como um utilizador com o perfil de “Subscritor” e ative as ações REST ou AJAX do plugin diretamente através de curl ou Postman. Se o servidor executa modificações ou revela dados da base de dados, faltam as camadas de permissões.
Se um agente de IA fizer parte desta revisão, o pacote security-audit da Cloudflare, publicado sob licença MIT (README lido em outubro de 2026), mostra como manter as conclusões fiáveis. Cada suspeita segue para um novo agente verificador que tenta refutá-la, pelo que o agente que verifica uma descoberta nunca é o que a encontrou. Uma pista que não se consegue provar fica marcada como needs_validation, sem gravidade atribuída, e não entra no relatório como vulnerabilidade. A falta de uma segunda camada de defesa, quando a primeira já bloqueia o ataque, conta como nota de reforço. A Cloudflare acrescenta que, nos seus próprios testes, uma única execução encontrou cerca de metade das vulnerabilidades encontradas no total por execuções repetidas. Num plugin gerado, uma passagem de IA é portanto um ponto de partida; o PHPCS, a lista de verificação para cada manipulador e os testes com privilégios baixos continuam a aplicar-se.
Atualização de . Há mais duas verificações para esta lista, e os plugins para WooCommerce precisam de ambas. A primeira diz respeito a mostrar um artigo ou produto pelo ID. Qualquer função que receba um ID de artigo ou produto de um pedido ou de um atributo de shortcode tem de verificar estado, visibilidade e palavra-passe antes de mostrar algo; caso contrário, um rascunho ou um produto privado ou protegido por palavra-passe expõe nome, preço ou imagem através de um shortcode, de uma vista rápida ou de uma lista de comparação. Procure no PHP get_post(, wc_get_product( e shortcode_atts(, siga cada ID até à saída e confirme que existe uma verificação de estado e visibilidade (como current_user_can( 'read_post', $id ) ou $product->is_visible()) e ainda post_password_required(). A segunda está no JavaScript. O WooCommerce dispara os eventos de variações e do carrinho através de jQuery, por isso um addEventListener nativo para nomes como found_variation ou updated_cart_totals nunca é acionado. Procure esses nomes no JavaScript e confirme que os ouvintes passam por jQuery, por exemplo jQuery( document.body ).on( 'updated_cart_totals', ... ).
Como executar o Plugin Check num plugin gerado por IA
O Plugin Check é a ferramenta com que o WordPress.org verifica os plugins face aos requisitos do diretório, e é igualmente útil num plugin privado que nunca vai ser submetido. A versão 2.1.0 saiu em agosto de 2026. Funciona em dois modos: verificações estáticas que leem o código, em parte com regras do PHP_CodeSniffer e em parte com regras próprias, e verificações em tempo de execução que ativam o plugin e executam partes dele. O projeto desaconselha usá-lo num site de produção, por isso instale-o em staging.
wp plugin check fjord-exporter
wp plugin check fjord-exporter --categories=security --format=csv --fields=code,type,severity,message
wp plugin check fjord-exporter --require=./wp-content/plugins/plugin-check/cli.phpA partir do WP-CLI só correm por predefinição as verificações estáticas; o terceiro comando carrega cli.php para que também corram as de tempo de execução. A lista de verificações coloca cinco delas na categoria security, e coincidem com os padrões deste guia:
| Verificação | O que assinala | Padrão neste guia |
|---|---|---|
direct_file_access | ficheiros PHP sem verificação de ABSPATH | acesso direto a ficheiros |
late_escaping | saída para o navegador sem escape | XSS |
direct_db | valores sem escape em consultas diretas à base de dados | injeção SQL |
direct_db_queries | consultas diretas à base de dados em geral | injeção SQL |
safe_redirect | wp_redirect() em vez de wp_safe_redirect() | redirecionamento aberto |
O conjunto de regras PHPCS da verificação plugin_review_phpcs carrega também as regras do WPCS para nonces, sanitização de entradas e SQL preparado, mas pertence à categoria plugin_repo, por isso --categories=security esconde esses resultados. Há ainda uma verificação que diz respeito ao código gerado: file_type assinala pastas de ferramentas de IA como .cursor, .claude, .aider, .continue, .windsurf e .ai que ficaram dentro do plugin porque a pasta dele era o diretório de trabalho de um assistente de programação. Cada resultado tem um tipo (ERROR ou WARNING) e uma gravidade de 1 a 10. O Plugin Check não sabe que capacidade um manipulador deveria exigir, por isso encurta a revisão manual sem a substituir.
Quando corrigir um plugin feito com IA e quando recuperar o site inteiro
Falhas localizadas (um handler AJAX, um formulário de administração) justificam uma correção depois da revisão. Quando os mesmos cinco padrões aparecem em vários ficheiros gerados, quando há funções inventadas ligadas a caminhos de produção ou quando os plugins escolhidos pela IA trazem CVE ativos além de código próprio fraco, pare de corrigir pontos isolados. A auditoria de recuperação de sites feitos por IA entrega uma divisão explícita entre manter, reescrever e remover, para não pagar uma reconstrução completa quando uma recuperação chega, nem corrigir sem fim quando a base não aguenta. Se o stack tiver ainda mais de trinta plugins e Core Web Vitals degradadas, junte a auditoria de código ao resgate de Core Web Vitals para sites feitos com IA.
O preço da recuperação e da auditoria é individual e definido depois desse inventário. Contacte-nos com o URL do plugin ou do site e a forma como o código foi gerado.
Resumo e recomendações
A inteligência artificial é um poderoso acelerador para escrever código, mas não pode assumir a responsabilidade da engenharia. Trate todo o código escrito pela IA como se tivesse sido redigido por um estagiário sem experiência.
Certifique-se de que implementa verificações de capacidades robustas (current_user_can()), verificação de CSRF (wp_verify_nonce()), parametrização de bases de dados ($wpdb->prepare()), sanitização de entradas e escape tardio de saídas. Ao combinar estas práticas principais com ferramentas de análise estático, pode escrever código de WordPress mais rápido enquanto mantém uma aplicação completamente segura.







