Aikido

Comment éviter les SELECT * en SQL : prévenir les fuites de données

Performance

Règle
Éviter SELECT * en SQL dans les requêtes SQL.
SELECT * dans production code fait applications
fragiles à schéma schémas et obscurcit données dépendances.

Langues prises en charge : 45+

Introduction

Utilisation SELECT * dans les requêtes de production permet de récupérer toutes les colonnes d'une table, y compris celles que votre application n'utilise pas. Lorsque les schémas de base de données évoluent et que de nouvelles colonnes sont ajoutées (y compris des données sensibles telles que des mots de passe ou des informations confidentielles), les requêtes utilisant la fonction SELECT * automatiquement les récupérer sans modifier le code. Cela crée des vulnérabilités en matière de sécurité et rompt les hypothèses de votre logique d'application.

Pourquoi c'est important

Impact sur les performances : L'extraction de colonnes inutiles augmente le temps d'exécution des requêtes, la taille du transfert réseau et la consommation de mémoire. Une table comportant 50 colonnes alors que vous n'en avez besoin que de 5 signifie que vous transférez 10 fois plus de données que nécessaire, ce qui dégrade les temps de réponse et augmente les coûts d'infrastructure.

Implications en matière de sécurité : Les nouvelles colonnes ajoutées aux tables (champs d'audit, drapeaux internes, données utilisateur sensibles) sont automatiquement exposées par l'intermédiaire de SELECT * des requêtes. Votre API peut commencer à divulguer des hachages de mots de passe, des numéros de sécurité sociale ou des données commerciales internes qui n'ont jamais été destinées à ce point de terminaison.

La maintenabilité du code : Quand SELECT * les requêtes sont interrompues après des modifications du schéma, l'erreur se produit au moment de l'exécution et non de la compilation. Une nouvelle colonne non annulable ou un champ renommé provoque des erreurs de production. Les listes de colonnes explicites clarifient les dépendances et interrompent la compilation lorsque les schémas changent de manière incompatible.

Exemples de code

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

Pourquoi c'est faux : cette requête récupère toutes les colonnes, y compris les champs potentiellement sensibles tels que password_hash, ssn, internal_notes ou deleted_at. Au fur et à mesure que le schéma se développe, cette requête devient plus lente et expose davantage de données, alors que l'application n'utilise que trois champs.

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

Conclusion

Spécifiez toujours des listes de colonnes explicites dans les requêtes SQL. Cela permet d'éviter les fuites de données, d'améliorer les performances et de clarifier les dépendances entre le code et le schéma. Le faible coût initial de la saisie des noms de colonnes permet d'éviter des catégories entières de problèmes de sécurité et de performances.

FAQ

Vous avez des questions ?

Quand le SELECT * est-il acceptable ?

Uniquement dans les requêtes ad hoc pendant le développement ou le débogage, jamais dans le code de production. Pour les scripts de migration de données ou les rapports uniques pour lesquels vous avez réellement besoin de toutes les colonnes, SELECT * est raisonnable. Pour le code d'application, utilisez toujours des listes de colonnes explicites, même si vous avez actuellement besoin de toutes les colonnes, car les changements de schéma sont inévitables.

Qu'en est-il des ORM qui génèrent des requêtes 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 * a-t-il un impact significatif sur les performances de la base de données ?

Oui, en particulier avec les tables larges. Les bases de données doivent lire plus de pages sur le disque, les index ne peuvent pas être utilisés aussi efficacement et les résultats des requêtes consomment plus de mémoire dans le pool de mémoire tampon de la base de données. Le temps de transfert sur le réseau augmente proportionnellement à la taille des données. Pour les tables comportant des colonnes TEXT ou BLOB, l'impact peut être important.

Comment gérer les requêtes pour lesquelles j'ai besoin du plus grand nombre de colonnes ?

Listez-les explicitement. Utilisez l'auto-complétion de votre IDE ou interrogez l'information_schema pour générer la liste des colonnes. Certaines équipes créent des objets de vue ou utilisent des vues de base de données qui définissent les colonnes exactes nécessaires pour chaque cas d'utilisation. La clarté et la sécurité des listes explicites l'emportent sur les inconvénients mineurs.

Comment détecter les SELECT * dans mon code ?

Recherchez le modèle SELECT * (insensible à la casse) dans votre base de données. De nombreux outils d'analyse statique et analyseurs de requêtes de bases de données peuvent les signaler. Lors de l'examen du code, rejetez tout PR contenant SELECT * dans le code de l'application. Certaines équipes utilisent des hooks de pré-commission ou des contrôles CI pour détecter et bloquer automatiquement ces modèles.

Obtenir la sécurité gratuitement

Sécurisez votre code, votre cloud et votre environnement d'exécution dans un système central.
Trouvez et corrigez rapidement et automatiquement les vulnérabilités.

Aucune carte de crédit n'est requise | Scanner les résultats en 32sec.