← Voltar ao blog

Como auditar extensões de terceiros no Magento 2

Rodrigo Biazzi

Uma loja Magento típica roda dezenas de módulos de terceiros. Alguns foram instalados para uma campanha que acabou anos atrás. Alguns vêm de fornecedores que não existem mais. Alguns adicionam um plugin em todo carregamento de produto por causa de um recurso usado em uma página. Cada um é código com acesso total ao banco e à requisição, escrito por alguém que você nunca revisou.

Uma auditoria de extensões responde três perguntas para cada módulo: ainda precisamos dele, é seguro e quanto custa em performance e esforço de upgrade. Este é o processo que eu sigo. Funciona para o Magento Open Source e o Adobe Commerce.

Passo 1: monte o inventário

Comece com uma lista completa do que está instalado e de onde veio:

bin/magento module:status
composer show --direct
ls app/code/*/
grep -h '"name"' app/code/*/*/composer.json 2>/dev/null

Coloque o resultado numa planilha com uma linha por módulo: nome, fornecedor, origem (Composer ou app/code), versão instalada, versão mais recente, ativado ou desativado e quem no negócio o usa. Deixe de fora o core do Magento e os módulos da Adobe. A última coluna é a que dá trabalho, porque a resposta muitas vezes está na memória de alguém. Pergunte para as pessoas que operam a loja, não só para os devs.

Módulos desativados mas ainda instalados também entram na lista. Eles continuam na base de código, continuam carregados pelo Composer e continuam precisando ser compatíveis no próximo upgrade.

Passo 2: confira o status de manutenção

composer outdated --direct
composer audit

O composer audit confere os pacotes instalados contra advisories de segurança públicos. O composer outdated mostra o quanto cada pacote está atrasado. Para cada extensão, confira também:

  • Quando o fornecedor lançou uma versão pela última vez
  • Se o fornecedor declara suporte à sua versão do Magento e do PHP
  • Se o fornecedor publica avisos de segurança e um changelog
  • Se você tem uma licença ativa, caso as atualizações exijam uma

Uma extensão sem release há dois ou três anos, numa plataforma que anda tão rápido, é um risco mesmo que funcione hoje. Ela vai bloquear o seu próximo upgrade de PHP ou de Magento, como descrito no guia de compatibilidade com PHP 8.

Passo 3: procure alertas de segurança

Você não precisa ler todas as linhas. Concentre-se no código que recebe entrada de fora.

Rotas públicas de web API

Confira o etc/webapi.xml de cada módulo em busca de rotas que qualquer um pode chamar:

grep -rn 'ref="anonymous"' vendor/*/*/etc/webapi.xml app/code/*/*/etc/webapi.xml

Rotas anônimas às vezes estão corretas, por exemplo um localizador de lojas público. Uma rota que retorna dados de pedido, dados de cliente ou altera algo sem autenticação é um problema sério.

Controllers do admin sem ACL

Controllers do admin estendem Magento\Backend\App\Action e devem definir uma constante ADMIN_RESOURCE ou sobrescrever _isAllowed(). Sem isso, qualquer usuário do admin, seja qual for o papel, pode chamar a action. Liste os controllers nas pastas Adminhtml e confira cada um.

Controllers do frontend que alteram dados

Um controller de frontend que salva ou apaga algo só deve aceitar POST. O framework valida o form key em requisições POST, e implementar HttpPostActionInterface faz a action rejeitar outros métodos HTTP. Controllers que alteram dados em GET ficam abertos a CSRF. Procure também controllers que implementam CsrfAwareActionInterface e desligam a validação, e confirme que há um bom motivo.

Padrões perigosos

grep -rnE "unserialize\(|eval\(|shell_exec\(|exec\(|system\(|move_uploaded_file\(" \
    vendor/somevendor app/code --include=*.php
  • SQL montado concatenando valores da requisição em vez de usar parâmetros com bind
  • unserialize() em dados que vêm de uma requisição ou cookie
  • Uploads de arquivo que não restringem extensões ou que gravam dentro da web root
  • Chamadas de saída para os servidores do fornecedor, para checagem de licença ou "estatísticas", que enviam dados da loja
  • PHP codificado ou ofuscado. Você não consegue auditar código que não consegue ler.

Cada resultado precisa de uma olhada humana. O objetivo é encontrar os poucos lugares que merecem uma revisão cuidadosa, não rejeitar um módulo por usar exec num comando de CLI.

Passo 4: meça o custo de performance

Extensões deixam lojas lentas de algumas formas previsíveis.

Plugins em caminhos quentes

Um plugin num método chamado centenas de vezes por requisição, como carregamento de produto, cálculo de preço ou geração de URL, multiplica o seu custo. Veja todos os plugins e preferences de uma classe com:

bin/magento dev:di:info "Magento\Catalog\Model\Product"
bin/magento dev:di:info "Magento\Quote\Model\Quote"

Plugins around merecem atenção extra. Eles adicionam uma chamada de closure e, se escritos sem cuidado, podem pular o método original ou outros plugins. Os prós e contras entre plugins, observers e preferences estão nesta comparação.

Observers em eventos frequentes

grep -rln -E "controller_action_predispatch|catalog_product_load_after|catalog_product_collection_load_after|layout_load_before" \
    vendor/*/*/etc/ app/code/*/*/etc/ --include=events.xml

Um observer em controller_action_predispatch roda em toda requisição. Um que faz uma query no banco ou uma chamada HTTP ali custa para todo visitante.

Peso no frontend

Veja quais módulos adicionam JavaScript e CSS em todas as páginas por arquivos de layout default.xml, e quais adicionam mixins do RequireJS. Um widget de chat, um popup e um selo de avaliações, cada um carregando a própria biblioteca, somam rápido no mobile.

Cron e banco de dados

Olhe o crontab.xml de cada módulo em busca de jobs que rodam a cada minuto, e as tabelas que o módulo cria. Tabelas de log que crescem sem limpeza são comuns.

A medida mais confiável é uma comparação. No staging, faça profiling de uma página de categoria, uma de produto e do checkout, depois desative um módulo suspeito e faça profiling de novo. Um profiler como Blackfire ou New Relic mostra exatamente qual plugin ou observer custa tempo.

Passo 5: decida

AchadoAção
Ninguém usa o recursoRemover o módulo
Usado, mantido, sem problemasManter, atualizar para a versão mais recente
Usado, desatualizado mas o fornecedor está ativoAtualizar, testar, manter
Usado, fornecedor sumiu ou código inseguroTrocar por recurso do core, outro fornecedor ou código customizado
Recurso pequeno, módulo pesadoTrocar por um módulo customizado pequeno

Remover costuma ser a escolha mais barata, mas precisa ser feito com cuidado por causa de tabelas, atributos e configurações que o módulo deixou para trás. Veja como remover um módulo do Magento com segurança.

Faça disso um hábito

Rode uma versão curta desta auditoria antes de todo upgrade e uma vez por ano no intervalo. Crie uma regra para novas extensões: antes de instalar, confira o fornecedor, a data do último release, o webapi.xml, os plugins que ela declara e se o código vem legível. Evitar um módulo ruim é muito mais barato que removê-lo depois.

FAQ

Quantas extensões são demais para o Magento 2?

Não há número fixo. O que importa é o que cada uma faz em toda requisição e se é mantida. Poucos módulos pesados em caminhos quentes prejudicam mais que muitas ferramentas pequenas do admin.

Como vejo todos os plugins de uma classe do Magento?

Rode o bin/magento dev:di:info com o nome da classe. Ele lista a preference, os argumentos do construtor e cada plugin com a ordem e o tipo.

É seguro usar extensões com PHP codificado?

É um risco, porque você não consegue revisar nem corrigir o código. Se precisar usar uma, mantenha atualizada e limite o acesso dela onde puder.

O que o composer audit confere?

Compara as versões dos pacotes instalados com advisories de segurança conhecidos e reporta os pacotes afetados. Não revisa código que não tem advisory publicado.

Atendo como freelancer em Magento e Adobe Commerce, incluindo auditorias e substituição de extensões. Se precisa de ajuda com isso, fale comigo.

Artigos relacionados