Bandit как linter на pre-commit
27 октября 2025 г.·211 views

🛠 Bandit как linter на pre-commit

Салют,

Давай сегодня посмотрим с тобой на SAST для python. Bandit смотрим как линтер, потому что удобно использовать без разбора и углубления в бизнес логику, потому что инструмент не умеет в это. Тебе же полезен для интеграции в команду разработки на python.

Bandit парсит код каждого файла проекта в AST (Abstract Syntax Tree - дерево абстрактного синтаксиса) и прогоняет набор правил (плагины через entry points). Тип лицензии: Apache-2.0 license. Форматы отчетов: csv, custom, html, json, screen, txt, xml, yaml.

Самое классное, что если использовать wemake-python-styleguide в совокупности с Bandit как анализатором, то мы решаем вопросы разименования, затенения встроенных функций, когнитивной сложность, а также проблемы с непоследовательными возвратами, неправильными разрывами строк, непоследовательными выражениями и сработка с явными уязвимостями.

Команды

python -m venv .venv

pip install bandit

bandir -r ./my_python_project/ # Рекурсивное сканирование

--severity-level

--confidence-level # Пороги

--profile

-t # Выбор правил

-s # Пропуск правил

nosec # Точечное игнорирование

docker pull ghcr.io/pycqa/bandit/bandit:<tag>

cosign verify ghcr.io/pycqa/bandit/bandit:latest &#092; # проверка подписи образа перед использованием

--certificate-identity https://github.com/pycqa/bandit/.github/workflows/build-publish-image.yml@refs/tags/<version> &#092;

--certificate-oidc-issuer https://token.actions.githubusercontent.com

Файл конфигурации

# .bandit

exclude_dirs: ['tests', 'venv']

skips: ['B101', 'B311']

any_other_function_with_shell_equals_true:

no_shell: ['subprocess.Popen']

hardcoded_password_string:

hardcoded_password_string_re: '(?i)(password|passwd|pwd)'

Использование как pre-commit

#.pre-commit-config.yaml

repos:

- repo: https://github.com/PyCQA/bandit

rev: 1.7.5

hooks:

- id: bandit

args: ['-ll', '-ii']

CI/CD

variables:

BANDIT_SEVERITY: "medium"

BANDIT_CONFIDENCE: "medium"

BANDIT_OUTDIR: "bandit-report"

bandit_scan:

stage: security

image: ghcr.io/pycqa/bandit/bandit:<tag>

script:

- mkdir -p "&#036;BANDIT_OUTDIR"

- bandit -r . &#092;

--severity-level="&#036;BANDIT_SEVERITY" &#092;

--confidence-level="&#036;BANDIT_CONFIDENCE" &#092;

-f json -o "&#036;BANDIT_OUTDIR/bandit.json"

pipeline {

agent any

options { timestamps() }

environment {

BANDIT_SEVERITY = 'medium'

BANDIT_CONFIDENCE = 'medium'

REPORT_DIR = 'bandit-report'

}

stages {

stage('Setup Python venv') {

steps {

sh '''

python3 -m venv .venv

. .venv/bin/activate

pip install --upgrade pip

pip install bandit

mkdir -p "&#036;{REPORT_DIR}"

'''

}

}

stage('Bandit Scan') {

steps {

sh '''

. .venv/bin/activate

bandit -r . --severity-level=&#036;{BANDIT_SEVERITY} --confidence-level=&#036;{BANDIT_CONFIDENCE} &#092;

-f json -o &#036;{REPORT_DIR}/bandit.json

bandit -r . --severity-level=&#036;{BANDIT_SEVERITY} --confidence-level=&#036;{BANDIT_CONFIDENCE} &#092;

-f sarif -o &#036;{REPORT_DIR}/bandit.sarif

bandit -r . --severity-level=&#036;{BANDIT_SEVERITY} --confidence-level=&#036;{BANDIT_CONFIDENCE} &#092;

-f html -o &#036;{REPORT_DIR}/bandit.html

'''

}

}

}

post {

always {

archiveArtifacts artifacts: 'bandit-report/**', fingerprint: true

}

unsuccessful {

script { currentBuild.result = 'UNSTABLE' }

}

}

}

Итого: сам SAST дает AST-подход без исполнения кода, где baseline позволяет внедрять постепенно и расширяем через плагины, но большое количество некорректных правила дающих FP, которые надо перебрать руками. Инструмент легковесен, но не как целевой SAST, а очень комфортное решение для проверок до Merge/ Pull Requeste. Совместно с wemake-python-styleguide решается проблема структуры и стилистики кода внутри команды разработки.

#toolchain #sast

#toolchain#sast
Открыть в Telegram