Aikido

Cómo evitar SELECT * en SQL: prevención de fugas de datos

Rendimiento

Regla
Evite SELECCIONE * en SQL consultas.
SELECT * en producción código hace que aplicaciones
frágiles a esquema cambios y oscurece datos dependencias.

Idiomas admitidos: 45+

Introducción

Utilizando SELECCIONAR * en las consultas de producción recupera todas las columnas de una tabla, incluidas las que la aplicación no utiliza. Cuando los esquemas de las bases de datos evolucionan y se añaden nuevas columnas (incluyendo datos sensibles como contraseñas o PII), las consultas que utilizan SELECCIONAR * empezar a recuperarlos automáticamente sin cambios en el código. Esto crea vulnerabilidades de seguridad y rompe suposiciones en la lógica de tu aplicación.

Por qué es importante

Impacto en el rendimiento: La recuperación de columnas innecesarias aumenta el tiempo de ejecución de la consulta, el tamaño de la transferencia de red y el consumo de memoria. Una tabla con 50 columnas cuando solo se necesitan 5 significa que se están transfiriendo 10 veces más datos de los necesarios, lo que degrada los tiempos de respuesta y aumenta los costes de infraestructura.

Implicaciones para la seguridad: Las nuevas columnas añadidas a las tablas (campos de auditoría, indicadores internos, datos sensibles de los usuarios) se exponen automáticamente a través de SELECCIONAR * consultas. Su API podría empezar a filtrar hashes de contraseñas, SSN o datos empresariales internos que nunca estuvieron destinados a ese punto final.

Mantenimiento del código: En SELECCIONAR * las consultas se rompen tras cambios en el esquema, el fallo se produce en tiempo de ejecución, no en tiempo de compilación. Una nueva columna no anulable o un campo renombrado provocan errores de producción. Las listas de columnas explícitas aclaran las dependencias y rompen las compilaciones cuando los esquemas cambian de forma incompatible.

Ejemplos de códigos

❌ No 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 qué es incorrecto: Esta consulta recupera todas las columnas, incluidos los campos potencialmente sensibles como password_hash, ssn, internal_notes o deleted_at. A medida que crece el esquema, esta consulta se vuelve más lenta y expone más datos, aunque la aplicación solo utiliza tres campos.

✅ Conforme:

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
    };
}

Conclusión

Especifique siempre listas de columnas explícitas en las consultas SQL. Esto evita fugas de datos, mejora el rendimiento y aclara las dependencias entre el código y el esquema. El pequeño coste inicial de escribir los nombres de las columnas evita toda una serie de problemas de seguridad y rendimiento.

Preguntas frecuentes

¿Tiene alguna pregunta?

¿Cuándo es aceptable SELECT *?

Sólo en consultas ad-hoc durante el desarrollo o la depuración, nunca en código de producción. Para scripts de migración de datos o informes puntuales en los que realmente necesite todas las columnas, SELECT * es razonable. Para el código de aplicación, utilice siempre listas de columnas explícitas, incluso si actualmente necesita todas las columnas, porque los cambios de esquema son inevitables.

¿Qué ocurre con los ORM que generan consultas 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.

¿Tiene SELECT * un impacto significativo en el rendimiento de la base de datos?

Sí, especialmente con tablas anchas. Las bases de datos deben leer más páginas del disco, los índices no se pueden utilizar con la misma eficacia y los conjuntos de resultados de las consultas consumen más memoria en el buffer de la base de datos. El tiempo de transferencia en red aumenta proporcionalmente al tamaño de los datos. Para las tablas con columnas TEXT o BLOB, el impacto puede ser grave.

¿Cómo gestiono las consultas en las que necesito la mayoría de las columnas?

Enumérelas explícitamente. Utiliza el autocompletado de tu IDE o consulta el information_schema para generar la lista de columnas. Algunos equipos crean objetos de vista o utilizan vistas de base de datos que definen las columnas exactas necesarias para cada caso de uso. La claridad y la seguridad de las listas explícitas compensan los pequeños inconvenientes.

¿Cómo detecto SELECT * en mi código base?

Busque el patrón SELECT * (sin distinguir mayúsculas de minúsculas) en su código. Muchas herramientas de análisis estático y analizadores de consultas de bases de datos pueden marcarlos. Durante la revisión del código, rechace cualquier PR que contenga SELECT * en el código de la aplicación. Algunos equipos utilizan ganchos de precompromiso o comprobaciones de CI para detectar y bloquear automáticamente estos patrones.

Asegúrese gratis

Proteja el código, la nube y el tiempo de ejecución en un sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

No requiere tarjeta de crédito | Escanea resultados en 32segs.