requirements.txt: strumento fondamentale o minaccia nascosta?
Ogni progetto Python ce l'ha. Quell'aspetto innocente requirements.txt situato alla radice del tuo repository, il file pip install requirements.txt consuma, è un elenco di dipendenze, certo, ma se non si sta attenti, può anche essere una porta spalancata verso build instabili, pacchetti vulnerabili e gravi problemi di sicurezza.
Nel suo nucleo, requirements.txt controlla quali pacchetti di terze parti vengono caricati dalla tua applicazione. Quando esegui pip installa -r requirements.txt, il gestore dei pacchetti di Python installa ogni dipendenza elencata. Ma ecco il punto: se non si fissano le versioni esatte, si è fidarsi di PyPI per fornire sempre una versione sicura, compatibile e non modificata, ogni volta. Non è così che funziona l'AppSec moderno.
Senza il pinning, le build possono interrompersi. Peggio ancora, l'applicazione potrebbe ingerire inconsapevolmente pacchetti dannosi. Versioning aperto (Pallone >=1.0, ad esempio) o vincoli di versione flessibili (django~=3.2) sono terreno fertile per l'iniezione di codice non sicuro. Ecco perché una gestione corretta requirements.txt è un compito fondamentale per la sicurezza.
Dove pip freeze e pip install requirements.txt Analisi
pip congelare è comodo, ma anche pericoloso se usato senza capire cosa cattura. Gli sviluppatori spesso generano requirements.txt utilizzando requisiti di congelamento pip.txt, aspettandosi che blocchi il loro ambiente. Ma freeze non convalida la sicurezza o l'origine delle dipendenze; si limita a scaricare tutto ciò che è attualmente installato, inclusi i pacchetti transitivi e potenzialmente obsoleti.
Ora immagina che un compagno di squadra, o il tuo CI, corra alla cieca pip installa -r requirements.txtSe quel file include elementi obsoleti, vulnerabili o addirittura pacchetti con errori di battitura, hai appena automatizzato un incidente di sicurezza.
Esempio rapido:
# Developer's freeze output
pip freeze > requirements.txt
boto3==1.24.20
requests==2.27.1
⚠️ Esempio non sicuro, non utilizzare in produzione
Ora aggiungilo al tuo CI pipeline:
- name: Install dependencies
run: pip install -r requirements.txt
Ti fidi che l'ambiente sia riproducibile, che nulla sia cambiato in PyPI e che ogni dipendenza è ancora sicuro. Questa è un'ipotesi enorme quando ci si affida a requisiti di congelamento pip.txt flussi di lavoro.
Minacce reali per la sicurezza delle applicazioni: typosquatting e confusione sulle dipendenze in requirements.txt
Gli aggressori adorano gli ecosistemi open source. Perché? Perché gli sviluppatori spesso si affidano a impostazioni predefinite e trust implicito. Ecco come colpiscono usando requirements.txt:
- Typosquatting: Caricamento di un pacchetto dannoso con un nome simile a richieste invece di richieste. Un personaggio in meno e la tua build è di tua proprietà.
richieste # ⚠️ Esempio illustrativo, non un vero pacchetto da installare
- Confusione delle dipendenze: Se il tuo pacchetto interno non è bloccato o non ha un ambito privato, gli aggressori possono pubblicare una versione dannosa su PyPI con lo stesso nome. Se la tua CI non convalida le fonti, installerai il loro pacchetto al posto del tuo.
Entrambi gli attacchi sfruttano la mancanza di un controllo rigoroso del pinning e della sorgente in requirements.txtSe il tuo dice solo qualche-libreria-internae tu corri requisiti di installazione pip.txt in CI, potrebbe recuperare il pacchetto sbagliato dal posto sbagliato.
Protezione di requirements.txt in CI/CD Pipelinecon hash e pinning
Ecco come indurire requirements.txt contro le minacce del mondo reale:
- Aggiungi le versioni esatte ai preferiti: Utilizzare sempre == per ogni pacchetto nel tuo requirements.txtNessun carattere jolly, nessun intervallo.
- Usa il –require-hash: Questo fa pip installa -r requirements.txt verificare l'integrità di ogni pacchetto scaricato.
Esempio:
flask==2.2.5 \
--hash=sha256:<actual_hash_here>
⚠️ Esempio dimostrativo, sostituire con hash reale nei progetti reali
- Isola le tue build: Costruisci sempre in contenitori puliti e minimali. Non fidarti mai ciecamente dell'immagine di base.
- Utilizzare un indice PyPI privato: Ospita il tuo proxy/cache e rispecchia solo i pacchetti attendibili.
Eseguire scansioni delle dipendenze: Integrare strumenti come pip-audit o usare SBOM-analisi basata sul tuo pipelines.
Esempio di frammento di GitHub Actions:
- name: Secure install
run: pip install --require-hashes -r requirements.txt
⚠️ Educativo pipeline ad esempio, adattarsi al tuo ambiente
Gestione rigorosa di pip installa -r requirements.txt in CI/CD è uno dei modi più semplici per ridurre i rischi dell'open source.
Build riproducibili: mantenerle stabili in tutti gli ambienti
Se la tua app funziona localmente ma non riesce in staging o prod, dipendenze incoerenti in requirements.txt sono i soliti sospettati. Anche una piccola deriva causa grossi problemi.
Utilizza queste strategie:
- pip-strumenti: Uso pip-compilare generare requirements.txt da parte di un requisiti.inRisolve le dipendenze con un pinning appropriato.
- Indicatori ambientali: Per pacchetti specifici del sistema operativo o dipendenze specifiche della versione di Python, utilizzare marcatori come piattaforma_sistema == 'Linux'.
- Memorizzazione nella cache Docker: In CI, memorizza nella cache i tuoi livelli Docker dopo aver installato le dipendenze da requirements.txt per ridurre la variabilità di costruzione.
Esempio con pip-tools:
# requirements.in
flask
# Compile
pip-compile requirements.in
⚠️ Esempio dimostrativo, l'output effettivo dipende dall'ambiente
L'uscita è completamente bloccata requirements.txt.
Strumenti come pip congelare, se combinato con pip installa -r requirements.txt durante le costruzioni, richiedono disciplina e misure di sicurezza aggiuntive.
Conclusione: definire con sicurezza i propri requisiti
cattiva gestione requirements.txt non è solo una cattiva pratica; è un rischio attivo per la sicurezza. Pinning lasco, installazioni non verificate e fiducia cieca nei registri aperti sono il modo in cui gli aggressori sfruttano il tuo CI/CD pipelineQuesti non sono difetti teorici; vengono sfruttati quotidianamente.
Il dependency pinning è più di una best practice. È la prima linea di difesa contro gli attacchi alla supply chain in Python. Combinalo con –require-hash, costruire isolamento e strumenti riproducibili come pip-strumenti, e ottieni un pipeline è più difficile scendere a compromessi.
Se stai usando requisiti di installazione pip.txt localmente o in CI, verifica e monitora sempre cosa entra nelle tue build. Strumenti come Xygeni fornire visibilità, applicazione delle policy e controlli automatizzati che bloccano la tua supply chain Python da requisiti di congelamento pip.txt durante tutta la produzione.





