Vai al contenuto

FRONTMATTER_48_# Bandit Python Security Linter Cheat Sheet

Traduzione:

Panoramica

Bandit è un linter di sicurezza progettato per trovare problemi di sicurezza comuni in codice Python. Analizza il codice sorgente Python e identifica le potenziali vulnerabilità di sicurezza attraverso la scansione di modelli noti e anti-patterns. Bandit è ampiamente usato nelle tubazioni DevSecOps per catturare i problemi di sicurezza presto nel processo di sviluppo, rendendolo uno strumento essenziale per lo sviluppo sicuro di Python.

Nota: Bandit è progettato per identificare potenziali problemi di sicurezza e dovrebbe essere utilizzato come parte di una strategia di test di sicurezza completa. Può produrre falsi positivi e dovrebbe essere combinato con altri metodi di test di sicurezza.

Installazione

Using pip

Traduzione:

Utilizzo di conda

Traduzione:

Utilizzo dei gestori dei pacchetti

Traduzione:

Installazione Docker

Traduzione:

Uso di base

Scansioni semplici

Traduzione:

Formati di output

Traduzione:

Severity and Confidence Filtering

Traduzione:

Configurazione

Configuration File (.bandit)

Traduzione:

pyproject.toml Configurazione

Traduzione:

Configurazione della riga di comando

Traduzione:

Uso avanzato

# Selezione di test personalizzata

Traduzione:

Baseline e scansione progressiva Traduzione:

Integrazione con Git

Traduzione:

.github/flows/security.yml

nome: Scansione di sicurezza

su:

lavori: bandit: run-on: ubuntu-latest passi: - usi: azioni/checkout@v3

  • nome: Impostare Python utilizza: azioni/setup-python@v4 con: python-version: 3.9.

  • nome: Installa Bandit run: pip install bandit[toml]

  • nome: Run Bandit run: bandit -r. -f json -o bandit-report.json

  • nome: Risultati di caricamento utilizza: azioni/upload-artifact@v3 con: nome: bandit-report percorso: bandit-report.json

  • nome: Bandit Report usi: tj-actions/bandit@v5.1 con: opzioni: "-r. -f json" uscita_zero: vero Traduzione:

.gitlab-ci.yml

fasi: - Sicurezza

bandit: stadio: sicurezza immagine: pitone:3.9 prima_script: - pip install bandit[toml] script: - bandit -r. -f json -o bandit-report.json artefatti: relazioni: sast: bandit-report.json percorsi: - bandit-report.json scaduto: 1 settimana consent_failure: vero Traduzione: // Jenkinsfile pipeline \ {} agente

fasi {} stadio('Scansione della sicurezza') \ {} Passi Traduzione: sh 'pip install bandit[toml] ' sh 'bandit -r. -f json -o bandit-report.json '

Traduzione: {} sempre. {} artefatti: 'bandit-report.json', impronta digitale: true pubblicareHTML([ consentire Mancante: falso, sempreLinkToLastBuild: vero, tenere tutto: vero, relazione Dir: '. reportFiles: 'bandit-report.html', reportName: "Bandit Security Report ' ]

Traduzione:

azure-pipelines.yml

trigger: - principale

piscina: vmImage: 'ubuntu-latest '

passi: - task: UsePythonVersion@0 ingressi: versione Spec: '3.9'

  • script:| pip install bandit[toml] bandit -r. -f json -o $(Agent.TempDirectory)/bandit-report.json displayName: 'Run Bandit Security Scan '

  • task: PublishTestResults@2 ingressi: testRisultatiFiles: '$(Agent.TempDirectory)/bandit-report.json ' test di prova RunTitle: 'Bandit Security Scan ' Traduzione:

BAD: Hardcoded password

password = "secret123" api_key = "abc123def456"

GOOD: variabili ambientali

importazione password = os.environ.get('PASSWORD') api_key = os.environ.get('API_KEY')

GOOD: File di configurazione

import configparser config = configparser.ConfigParser() config.read('config.ini') password = config.get('database', 'password') Traduzione:

BAD: formattazione dello stress

query = "SELECT * DAgli utenti DOVE id = %" % user_id query = f"SELECT * DAgli utenti DOVE id = \{user_id\}"

GOOD: Domande parametrizzate

cursor.execute("SELECT * DAgli utenti DOVE id = %", (user_id,)) cursor.execute("SELECT * DAgli utenti DOVE id = ?", (user_id,) Traduzione:

BAD: iniezione conchiglia

importazione os.system(f)ls \{user_input\} os.popen(f)grep \{pattern\} \{filename\}

GOOD: Sottoprocesso con lista

importazione subprocesso subprocess.run(['ls', user_input]) subprocess.run(['grep', pattern, filename]) Traduzione:

BAD: Predictable random

importazione casuale token = random.randint(1000, 9999)

GOOD: Crittograficamente sicuro

segreti di importazione token = secrets.randbelow(9999) safe_token = secrets.token_hex(16) Traduzione:

BAD: carico non sicuro YAML

importazione yaml dati = yaml.load (user_input)

GOOD: caricamento sicuro YAML

dati = yaml.safe_load (user_input) dati = yaml.load (user_input, Loader=yaml.SafeLoader) Traduzione:

custom_bandit_test.py

import bandit dal bandito. core import test_properties

@test_properties.test_id('B999') @test_properties.checks('Call') def custom_security_check(context): """Check for custom security pattern"" se context.call_function_name_qual == 'dangerous_function': ritorno bandito. Fascicolo severity=bandit. Grandioso. fiducia=bandit. Grandioso. testo="Usa di pericolosa_funzione rilevata", lineno=context.node.lineno,

Traduzione:

bandit_plugin.py

dal bandito. estensione dell'importazione del nucleo_loader

def load_tests(): ""Prove personalizzate"" [custom_security_check]

Registrare plugin

estensione_loader.MANAGER.register_plugin('custom_tests', load_tests) Traduzione:

Carica test personalizzati

bandit -r. --tests custom_bandit_test.py

Utilizzare il plugin

bandito -r. --plugin bandit_plugin.py Traduzione:

!/usr/bin/env python3

bandit_scanner.py

importazione subprocesso importazione json import sys import argparse da pathlib import Sentiero

classe BanditScanner: def init(self, project_path, config_file=Noe): self.project_path = Path(project_path) self.config_file = config_file auto.risultati = \{}

def run_scan(self, output_format='json', severity='MEDIUM', trust='MEDIUM'): ""Run Bandit scansione con parametri specificati""" cmd = 'bandit', '-r', str(self.project_path), '-f', output_format, f'-l{self._severity_to_flag(severity)\}, f'-i{self._confidence_to_flag(confidence)\} ' ]

se self.config_file: cmd.extend(['--configfile', self.config_file])

prova: risultato = subprocess.run(cmd, catch_output=True, text=True, check=False)

se output_format == 'json': self.results = json.loads(result.stdout) se risultato. Esclusivamente Altro: self.results = risultato.stdout

restituire il risultato.returncode == 0

eccetto sottoprocesso. ChiamatoProcess Errore come: stampa(f"Error in esecuzione Bandit: \{e\}") ritorno Falso tranne json. JSONDecode Errore come: stampa(f"Error parsing JSON output: \{e}") ritorno Falso

def _severity_to_flag(self, severity): ""Converti la gravità alla Bandit flag"" mapping = \{'LOW': '', 'MEDIUM': 'l', 'HIGH': 'll'} rimbalzare. ottenere(severity.upper(), 'l')

def _confidence_to_flag(self, trust): ""Convertire la fiducia nella bandiera Bandit"" mapping = \{'LOW': 'ii', 'MEDIUM': 'i', 'HIGH': '\} ritorno mapping.get (confidence.upper(), 'i')

def get_summary(self): ""Riepilogo della scansione"" se non èinstanza(autorisultati, ditta): ritorno "Nessun risultato disponibile"

metriche = self.results.get('metrics', \{}) Restituzione 'total_lines': metrics.get('_totals', \\}).get('loc', 0), 'total_issues': len(self.results.get('results', []), 'high_severity': len([r per r in self.results.get('results', []) se r.get('problem_severity') == 'HIGH']), 'medium_severity': len([r per r in self.results.get('results', []) se r.get('problem_severity') == 'MEDIUM']), 'low_severity': len([r per r in self.results.get('results', []) se r.get('problem_severity') == 'LOW')

def get_issues_by_severity(self, severity='HIGH'): """I problemi della gravità"" se non èinstanza(autorisultati, ditta): []

[problema per emissione in self.results.get('results', []) se issue.get('issue_severity') == severity.upper()

def generare_report(self, output_file='bandit_report.html'): ""Generate HTML report"" cmd = 'bandit', '-r', str(self.project_path), '-f', 'html', '-o', output_file ]

se self.config_file: cmd.extend(['--configfile', self.config_file])

prova: sottoprocess.run(cmd, check=True) Ritorno Vero eccetto sottoprocesso. ChiamatoProcess Errore: ritorno Falso

def save_results(self, output_file='bandit_results.json'): ""Salva risultati a file"" se isinstance(self.results, dict): con aperto (output_file, 'w') come f: json.dump(self.results, f, indent=2) Altro: con aperto (output_file, 'w') come f: f.write(str(self.results)))

def principale(): parser = argparse. ArgumentParser(descrizione='Automated Bandit Scanner') parser.add_argument('project_path', help='Path to project to scan') parser.add_argument('--config', help='Bandit file di configurazione') parser.add_argument('--severity', default='MEDIUM', Traduzione: help='Minimum severity level') parser.add_argument('--confidence', default='MEDIUM', Traduzione: help='Minimo livello di fiducia') parser.add_argument('--output', help='Output file for results') parser.add_argument('--report', help='Generate HTML report')

args = parser.parse_args()

scanner = BanditScanner (args.project_path, args.config)

stampa(f)Scanning \{args.project_path\}... successo = scanner.run_scan(severity=args.severity, trust=args.confidence)

se il successo: sommario = scanner.get_summary() stampa(f"Scan completato con successo!") print(f)Total lines of code: \{summary['total_lines']}") stampa(f) Problemi totali trovati: \{summary['total_issues']}") stampa(f"High severity: \{summary['high_severity']}") stampa(f) gravità media: \{summary['medium_severity']}] stampa(f)Low severity: \{summary['low_severity']}]

Se args. uscita: scanner.save_results(args.output) stampa(f"Risultati salvati su \{args.output\}

se args.report: se scanner.generate_report(args.report): stampa(f"HTML report generato: \{args.report\}") Altro: print("Failed per generare report HTML")

Esci con il codice di errore se i problemi di alta gravità trovati

se il riassunto ['high_severity'] > `` 0: stampa("I problemi di gravità trovati!") sys.exit(1) Altro: stampa("Scan ha fallito!" sys.exit(1)

'main_':

principale() Traduzione:

lot_bandit_scan.sh

Configurazione

PROJECTS_DIR="/path/to/projects" RELAZIONI_DIR="/percorso/riportazioni" Traduzione: +% Y%m%d_%H%M%S)

Crea la directory dei report

mkdir -p "$REPORTS_DIR"

Funzione per la scansione del progetto

) progetto locale_path="\(1" progetto locale_name=\)(basename "\(project_path") report_file="\)REPORTS_DIR/\(\{project_name\}_\){DATE}.json" html_report="$ RELAZIONI_DIR/\(\{project_name\}_\){DATE}.html

echo "Scanning $project_name..."

Run Bandit scan

bandit -r "\(project_path" -f json -o "\)report_file" -ll -ii bandit -r "\(project_path" -f html -o "\)html_report" -ll -ii

Controllare i problemi di alta gravità

high_issues=\((jq '.results|map(select(.issue_severity == "HIGH"))|length" "\)report_file")

se ["$high_issues" -gt 0 ]; allora echo "WARNING: \(project_name ha \(high_issues ad alta gravità problemi!" echo "\)project_name" > "\)REPORTS_DIR/high_severity_projects.txt"

echo "Scan completato per $project_name"

Scansione di tutti i progetti Python

trovare "\(PROJECTS_DIR" -name "*.py" -type f|while read -r file; do project_dir=\)(dirname "\(file") se [! -f "\)project_dir/.bandit_scanned" ]; allora scan_project "\(project_dir" toccare "\)project_dir/.bandit_scanned"

Fatto

eco "Batch scansione completata. Rapporti salvati a $REPORTS_DIR" Traduzione: // .vscode/settings.json . {} "python.linting.banditEnabled": vero, "python.linting.banditArgs": [ "--severity-level", "medium", "-livello di fiducia", "medium" ] "python.linting.enabled": vero

Traduzione:

Configurazione degli strumenti esterni

Programma: bandit

Argomenti:

directory di lavoro: \(ProjectFileDir\)

Traduzione: .vimrc o init.vim " Integrazione Bandit con ALE g:ale_linters = ['bandit', 'flake8', 'pylint'],

let g:ale_python_bandit_options = '-ll -ii ' Traduzione:

.bandit - Configurazione completa

B30, B305, B30

skips: ['B101'] # Salta assert_used in file di test

escludere_dirs: [ /test/, /test/, /.venv/, /venv/, /.env/, /env/, /migrazioni/, /node_modules/, /.git/ ]

Punti positivi: LOW, MEDIUM, HIGH

gravità: MEDIUM

Confidenza: LOW, MEDIUM, HIGH

fiducia: MEDIUM Traduzione:

Inline commenti per sopprimere gli avvisi

password = "default" # nosec B105

Suppress test specifico

importazione subprocesso subprocess.call(shell_command, shell=True) # nosec B602

Supprimere più test

eval(user_input) # Nosec B307, B102 # Traduzione:

Configurazione pre-commit (.pre-commit-config.yaml)

repos: - Repo: 1,7.5. ganci: - id: bandit ['-ll', '-ii'] escludere:

Rendere l'integrazione dei file

. PHONY: sicurezza-scan sicurezza-scan: bandit -r. -ll -iii -f json -o security-report.json @echo "Security scan completato. Controllare la sicurezza-report.json per i risultati."

. PHONY: controllo di sicurezza controllo di sicurezza: bandit -r. -ll -ii @if [ $? echo "I problemi di sicurezza trovati. Si prega di rivedere e correggere."; . uscita 1; \

Traduzione:

Fascicolo: Importazione Errore durante l'esecuzione di Bandit

Soluzione: Assicurare un ambiente Python corretto

python -m pip install --upgrade bandit

Problema: la configurazione non viene letta

Soluzione: Verificare la posizione del file di configurazione e la sintassi

bandito --help-config

Numero: Troppi falsi positivi

Soluzione: Configurazione dei sintoni e soppressione dell'uso

bandito - B101, B601 -ll -iii

Problema: problemi di prestazioni con grandi codebases

Soluzione: Escludere directory inutili

bandit -r. --escluso "/venv/,/node_modules/,/.git/"

Problema: Integrazione con CI/CD guasto

Soluzione: Utilizzare i codici di uscita appropriati e la gestione degli errori

bandit -r. -ll -ii||true # Continua sugli errori Traduzione:

Lavorazione parallela (se disponibile)

bandit -r. --processi 4

Escludere grandi directory

/venv/,/env/,/node_modules/,/.git/,/migrazioni/

Utilizzare solo prove specifiche

bandit -r. --test B201, B301, B401, B501

Limite profondità di ricorsione

-name ".py" -not -path "/venv/*"|head -100|xargs bandit Traduzione:

Uscita Verbose

bandit -v -r.

Modalità Debug

bandit -d -r.

Mostra i file saltati

bandit -r. --verbose

Test di file specifici con tutti i dettagli

bandit -v -ll -iii specific_file.py Traduzione:

Integrazione CI/CD

GitHub Azioni

Traduzione:

GitLab CI

Traduzione:

Jenkins Pipeline

Traduzione:

Azure DevOps

Traduzione:

Modelli comuni di vulnerabilità

Password con codice rigido (B105, B106, B107)

Traduzione:

SQL Injection (B608)

Traduzione:

Iniezione di comando (B602, B605, B606, B607)

Traduzione:

Insecure Random (B311)

Traduzione:

Unsafe YAML Caricamento (B506)

Traduzione:

Regole e Plugin personalizzati

Creare test personalizzati

Traduzione:

Plugin Development

Traduzione:

Usando i test personalizzati

Traduzione:

Automation and Scripting

Script di scansione automatizzato

Traduzione:

Batch Processing Script

Traduzione:

Integrazione con IDEs

VS Code Integration

Traduzione:

PyCharm Integrazione

Traduzione:

Vim/Neovim Integrazione

Traduzione:

Migliori Pratiche

Gestione configurazione

Traduzione:

False Positive Management

Traduzione:

Team Workflow Integration

Traduzione:

Risoluzione dei problemi

Questioni comuni

Traduzione:

Ottimizzazione delle prestazioni

Debugging

Traduzione:

Risorse


*Questo foglio di scacchi fornisce una guida completa per l'utilizzo di Bandit per identificare le vulnerabilità di sicurezza nel codice Python. Combina sempre l'analisi statica con altri metodi di test di sicurezza per una copertura completa. *