Aikido

Come evitare l'uso di SELECT * in SQL: prevenire la fuga di dati

Prestazioni

Regola
Da evitare SELECT * in SQL .
SELECT * nelle produzione codice rende le applicazioni
fragili rispetto schema modifiche e nasconde dipendenza dipendenze.

Linguaggi supportati: 45+

Introduzione

Utilizzo di SELECT * nelle query di produzione recupera tutte le colonne di una tabella, comprese quelle che la tua applicazione non utilizza. Quando gli schemi dei database si evolvono e vengono aggiunte nuove colonne (compresi dati sensibili come password o informazioni personali identificative), le query che utilizzano SELECT * iniziare automaticamente a recuperarli senza modifiche al codice. Ciò crea vulnerabilità di sicurezza e compromette i presupposti alla base della logica dell'applicazione.

Perché è importante

Impatto sulle prestazioni: il recupero di colonne non necessarie aumenta il tempo di esecuzione delle query, la quantità di dati trasferiti in rete e il consumo di memoria. Una tabella con 50 colonne, quando ne servono solo 5, comporta il trasferimento di una quantità di dati 10 volte superiore al necessario, con conseguente peggioramento dei tempi di risposta e aumento dei costi dell'infrastruttura.

Implicazioni in materia di sicurezza: Le nuove colonne aggiunte alle tabelle (campi di audit, flag interni, dati sensibili degli utenti) vengono automaticamente rese visibili tramite SELECT * richieste. La tua API potrebbe iniziare a divulgare hash delle password, numeri di previdenza sociale o dati aziendali interni che non erano mai stati destinati a quell’endpoint.

Manutenibilità del codice: Quando SELECT * Le query smettono di funzionare dopo le modifiche allo schema; l'errore si verifica in fase di esecuzione, non in fase di compilazione. Una nuova colonna non nullabile o un campo rinominato causano errori in produzione. Gli elenchi espliciti delle colonne rendono chiare le dipendenze e interrompono le build quando gli schemi subiscono modifiche incompatibili.

Esempi di codice

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

Perché è sbagliato: questa query recupera tutte le colonne, compresi campi potenzialmente sensibili come password_hash, ssn, internal_notes o deleted_at. Man mano che lo schema cresce, questa query diventa più lenta ed espone una quantità maggiore di dati, nonostante l'applicazione ne utilizzi solo tre.

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

Conclusione

Nelle query SQL specificare sempre elenchi espliciti di colonne. Ciò previene la fuga di dati, migliora le prestazioni e rende chiare le dipendenze tra codice e schema. Il modesto sforzo iniziale richiesto dalla digitazione dei nomi delle colonne consente di evitare intere categorie di problemi relativi alla sicurezza e alle prestazioni.

Domande frequenti

Hai delle domande?

Quando è accettabile l'uso di SELECT *?

Solo nelle query ad hoc durante lo sviluppo o il debug, mai nel codice di produzione. Per gli script di migrazione dei dati o i report una tantum in cui è effettivamente necessario utilizzare tutte le colonne, l'uso di SELECT * è giustificato. Per il codice dell'applicazione, utilizzare sempre elenchi espliciti di colonne anche se al momento sono necessarie tutte le colonne, poiché le modifiche allo schema sono inevitabili.

E che dire degli ORM che generano query 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.

L'istruzione SELECT * influisce in modo significativo sulle prestazioni del database?

Sì, soprattutto nel caso di tabelle di grandi dimensioni. I database devono leggere un numero maggiore di pagine dal disco, gli indici non possono essere utilizzati in modo altrettanto efficace e i risultati delle query occupano più memoria nel buffer pool del database. Il tempo di trasferimento in rete aumenta in proporzione alla dimensione dei dati. Per le tabelle con colonne di tipo TEXT o BLOB, l'impatto può essere notevole.

Come devo gestire le query in cui mi servono la maggior parte delle colonne?

Elencale in modo esplicito. Utilizza la funzione di completamento automatico del tuo IDE oppure esegui una query su `information_schema` per generare l'elenco delle colonne. Alcuni team creano oggetti di visualizzazione o utilizzano viste del database che definiscono le colonne esatte necessarie per ciascun caso d'uso. La chiarezza e la sicurezza derivanti dall'uso di elenchi espliciti superano di gran lunga il leggero inconveniente.

Come faccio a individuare le istruzioni SELECT * nel mio codice?

Cerca il pattern SELECT * (senza distinzione tra maiuscole e minuscole) nel tuo codice. Molti strumenti di analisi statica e analizzatori di query di database sono in grado di individuarli. Durante la revisione del codice, respingi qualsiasi pull request che contenga SELECT * nel codice dell'applicazione. Alcuni team utilizzano hook pre-commit o controlli CI per rilevare e bloccare automaticamente questi pattern.

Metti in sicurezza ora

Metti in sicurezza il tuo codice, il cloud e il runtime in un unico sistema centralizzato.
Trova e risolvi le vulnerabilità rapidamente e automaticamente.

Nessuna carta di credito richiesta | Risultati della scansione in 32 secondi.