Bandit Python Security Linter Cheat Sheet
Traduzione: Copia tutti i comandi
Traduzione: Generare PDF
< >
## 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
### Utilizzo di pip
Traduzione:
### Utilizzo di conda
Traduzione:
### Utilizzo dei gestori dei pacchetti
Traduzione:
### Installazione Docker
Traduzione:
## Uso di base
### Scansioni semplici
Traduzione:
### Formati di uscita
Traduzione:
### Filtro della gravità e della fiducia
Traduzione:
## Configurazione
### File di configurazione (.bandit)
Traduzione:
### pyproject.toml Configurazione
Traduzione:
### Configurazione della riga di comando
Traduzione:
## Uso avanzato
### Selezione test personalizzata
Traduzione:
### Baseline e scansione progressiva
Traduzione:
### Integrazione con Git
Traduzione:
# .github/flusso di lavoro/security.yml
nome: Scansione di sicurezza
su:
lavori:
bandit:
run-on: ubuntu-latest
passi:
- utilizza: 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 '
- attività: PublishTestResults@2
ingressi:
testRisultatiFiles: '$(Agent.TempDirectory)/bandit-report.json '
test di prova RunTitle: 'Bandit Security Scan '
Traduzione:
# BAD: password codificata
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 della stringa
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: casuale prevedibile
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")
# Exit with error code if high severity issues found
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:
#!/bin/bash
# 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
# Check for high severity issues
| 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: -r $FileDir$ -f json
# 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:
# Osservazioni in linea 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:
# Problema: ImportError quando si esegue 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
# Problema: 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
# Limitare la 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:
## Vulnerabilità comune Modelli
### Password con codice rigido (B105, B106, B107)
Traduzione:
### SQL Injection (B608)
Traduzione:
### Iniezione di comando (B602, B605, B606, B607)
Traduzione:
### Insicuro Random (B311)
Traduzione:
### Caricamento non sicuro YAML (B506)
Traduzione:
## Regole e Plugin personalizzati
### Creazione di test personalizzati
Traduzione:
### Sviluppo del plugin
Traduzione:
### Utilizzo di test personalizzati
Traduzione:
## Automazione e scrittura
### Script di scansione automatizzato
Traduzione:
### script di elaborazione batch
Traduzione:
## Integrazione con IDE
### Integrazione del codice VS
Traduzione:
### Integrazione PyCharm
Traduzione:
### Integrazione Vim/Neovim
Traduzione:
## Migliori Pratiche
### Gestione della configurazione
Traduzione:
### Falsa gestione positiva
Traduzione:
### Integrazione del flusso di lavoro del team
Traduzione:
## Risoluzione dei problemi
### Questioni comuni
Traduzione:
### Ottimizzazione delle prestazioni
#
### Debug
Traduzione:
## Risorse
- [Bandit Documentazione ufficiale](__LINK_6__]
-%20[Bandit%20GitHub%20Repository](__LINK_6__)
- [Python Security Best Practices](__LINK_6__)
- [OWASP Python Security](__LINK_6__]
-%20[PyCQA%20Tools](__LINK_6__)
---
*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. *