Aikido

Como evitar SELECT * em SQL: prevenindo vazamentos de dados

Desempenho

Regra
Evitar SELECCIONAR * em SQL queries.
SELECT * em produção código produz aplicações
frágeis para esquema alterações e obscurece dados dependências.

Idiomas suportados: 45+

Introdução

Utilizando SELECT * em queries de produção recupera todas as colunas de uma tabela, incluindo colunas que sua aplicação não usa. Quando esquemas de banco de dados evoluem e novas colunas são adicionadas (incluindo dados sensíveis como senhas ou PII), queries usando SELECT * comece a recuperá-los automaticamente sem alterações no código. Isso cria vulnerabilidades de segurança e quebra suposições na lógica da sua aplicação.

Por que isso importa

Impacto no desempenho: A recuperação de colunas desnecessárias aumenta o tempo de execução da query, o tamanho da transferência de rede e o consumo de memória. Uma tabela com 50 colunas onde você precisa apenas de 5 significa que você está transferindo 10 vezes mais dados do que o necessário, degradando os tempos de resposta e aumentando os custos de infraestrutura.

Implicações de segurança: Novas colunas adicionadas a tabelas (campos de auditoria, flags internas, dados sensíveis de usuários) são automaticamente expostas através de SELECT * consultas. Sua API pode começar a vazar hashes de senhas, SSNs ou dados internos de negócios que nunca foram destinados para aquele endpoint.

Manutenibilidade do código: Quando SELECT * consultas quebram após alterações de esquema, a falha ocorre em tempo de execução, não em tempo de compilação. Uma nova coluna não nula ou um campo renomeado causa erros de produção. Listas explícitas de colunas deixam as dependências claras e quebram as builds quando os esquemas mudam de forma incompatível.

Exemplos de código

❌ Não-conforme:

async function getUserProfile(userId) {
    const query = 'SELECT * FROM users WHERE id = ?';
    const [user] = await db.execute(query, [userId]);

    return {
        name: user.name,
        email: user.email,
        createdAt: user.created_at
    };
}

Por que está errado: Isso recupera todas as colunas, incluindo campos potencialmente sensíveis como password_hash, ssn, internal_notes ou deleted_at. À medida que o schema cresce, esta query se torna mais lenta e expõe mais dados, embora a aplicação utilize apenas três campos.

✅ Compatível:

async function getUserProfile(userId) {
    const query = `
        SELECT name, email, created_at
        FROM users
        WHERE id = ?
    `;
    const [user] = await db.execute(query, [userId]);

    return {
        name: user.name,
        email: user.email,
        createdAt: user.created_at
    };
}

Conclusão

Sempre especifique listas explícitas de colunas em consultas SQL. Isso evita vazamentos de dados, melhora o desempenho e torna claras as dependências entre código e esquema. O pequeno custo inicial de digitar os nomes das colunas evita classes inteiras de problemas de segurança e desempenho.

FAQs

Dúvidas?

Quando SELECT * é aceitável?

Apenas em consultas ad-hoc durante o desenvolvimento ou depuração, nunca em código de produção. Para scripts de migração de dados ou relatórios pontuais onde você realmente precisa de todas as colunas, SELECT * é razoável. Para código de aplicação, sempre use listas de colunas explícitas, mesmo que você precise de todas as colunas atualmente, pois as mudanças de esquema são inevitáveis.

E quanto aos ORMs que geram queries SELECT *?

Configure your ORM to select specific fields. Most ORMs (Sequelize, TypeORM, Prisma, SQLAlchemy) support field selection: User.findOne({ attributes: ['name', 'email'] }) or prisma.user.findUnique({ select: { name: true, email: true } }). Always use these options to control what data is retrieved.

SELECT * impacta significativamente o desempenho do banco de dados?

Sim, especialmente com tabelas largas. Bancos de dados devem ler mais páginas do disco, índices não podem ser usados com a mesma eficácia, e conjuntos de resultados de consultas consomem mais memória no pool de buffer do banco de dados. O tempo de transferência de rede aumenta proporcionalmente ao tamanho dos dados. Para tabelas com colunas TEXT ou BLOB, o impacto pode ser severo.

Como lidar com consultas onde preciso da maioria das colunas?

Liste-os explicitamente. Use o auto-complete da sua IDE ou consulte o information_schema para gerar a lista de colunas. Algumas equipes criam objetos de visualização ou usam views de banco de dados que definem as colunas exatas necessárias para cada caso de uso. A clareza e a segurança das listas explícitas superam o pequeno inconveniente.

Como detectar SELECT * na minha base de código?

Procure pelo padrão SELECT * (não sensível a maiúsculas e minúsculas) em sua base de código. Muitas ferramentas de análise estática e analisadores de consulta de banco de dados podem sinalizá-los. Durante a revisão de código, rejeite qualquer PR que contenha SELECT * no código da aplicação. Algumas equipes usam hooks de pré-commit ou verificações de CI para detectar e bloquear automaticamente esses padrões.

Fique seguro agora

Proteja seu código, Cloud e runtime em um único sistema centralizado.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados da varredura em 32 segundos.