agentsclimarketplace

Bandit

Skill kpatryk/skills/skills/bandit

AI skills

Install
npx -y skills add kpatryk/skills --skill bandit

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Comprehensive reference for Bandit — the Python AST-based security linter from PyCQA that detects common security vulnerabilities in Python code. Use this skill whenever the user asks about running Bandit scans, interpreting Bandit findings, suppressing false positives with nosec, configuring Bandit via pyproject.toml or bandit.yaml, selecting or skipping specific test IDs (B101–B704), setting up Bandit in CI/CD, generating baselines to track new issues, or integrating Bandit with pre-commit. Trigger on any mention of bandit, Python security scanning, SAST for Python, hardcoded passwords in Python, SQL injection detection, shell injection in Python, pickle deserialization, or insecure Python imports.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

8.7 KB, as published. Nobody here has run it

Bandit

Bandit is a Python security linter by PyCQA that walks the AST of each file and runs security-focused plugin tests against the nodes. It reports findings with both severity and confidence levels (LOW / MEDIUM / HIGH).

Official docs: https://bandit.readthedocs.io/en/latest/
Source: https://github.com/PyCQA/bandit

Installation

pip install bandit                  # core
pip install "bandit[toml]"          # adds pyproject.toml config support
pip install "bandit[baseline]"      # adds bandit-baseline CLI
pip install "bandit[sarif]"         # adds SARIF output formatter

Core usage

# Recursively scan a project
bandit -r src/

# Scan specific files or glob
bandit app.py utils/*.py

# Read from stdin
cat app.py | bandit -

Common flags

FlagDescription
-rRecurse into directories
-l / --levelMinimum severity: use -l (LOW+), -ll (MEDIUM+), -lll (HIGH only)
-i / --confidenceMinimum confidence: -i (LOW+), -ii (MEDIUM+), -iii (HIGH only)
--severity-level LOW|MEDIUM|HIGHFilter by minimum severity (long form)
--confidence-level LOW|MEDIUM|HIGHFilter by minimum confidence
-t B101,B307Run only these test IDs
-s B101,B311Skip these test IDs
-n 3Show N lines of code context per finding
-f text|json|csv|xml|html|screen|sarifOutput format
-o results.jsonWrite output to file
-c bandit.yamlUse a YAML or TOML config file
--ini .banditUse an INI config file
--exclude tests,venvComma-separated paths to exclude
--baseline baseline.jsonCompare against a baseline; only show new issues
-b baseline.jsonShort form of --baseline
-p ShellInjectionRun a named profile
-qQuiet mode (suppress progress output)
-vVerbose mode

Output formats

bandit -r src/ -f json -o bandit-results.json
bandit -r src/ -f html -o bandit-report.html
bandit -r src/ -f sarif -o bandit.sarif        # GitHub code scanning
bandit -r src/ -f screen                        # colored terminal output

Severity & confidence filtering

# Only HIGH severity, any confidence
bandit -r . -lll

# MEDIUM+ severity AND MEDIUM+ confidence
bandit -r . -ll -ii

# HIGH severity and HIGH confidence only
bandit -r . -lll -iii

# Long-form equivalents
bandit -r . --severity-level HIGH --confidence-level HIGH

Selecting / skipping tests

# Run only specific tests
bandit -r . -t B102,B307,B602

# Skip tests (e.g. skip assert_used in test directories)
bandit -r . -s B101

# Combine: run only B3xx blacklist calls, but skip B311 (random)
bandit -r . -t B301,B302,B303,B304,B305,B306,B307,B308,B310,B311 -s B311

Configuration files

pyproject.toml (recommended)

[tool.bandit]
exclude_dirs = ["tests", "venv", ".tox"]
skips = ["B101", "B311"]
tests = []   # empty = run all (after applying skips)

[tool.bandit.any_other_function_with_shell_equals_true]
shell = ["os.system", "os.popen"]

Run with: bandit -c pyproject.toml -r .

bandit.yaml

exclude_dirs: ['tests', 'path/to/file']
tests: ['B201', 'B301']
skips: ['B101', 'B601']

Run with: bandit -c bandit.yaml -r .

.bandit (INI — auto-detected when using -r)

[bandit]
targets = src,lib
exclude = tests,build
skips = B101,B311
tests = B201,B301

Bandit auto-discovers .bandit only when invoked with -r. For other filenames: bandit --ini tox.ini.

Generate a starter config

bandit-config-generator > bandit.yaml
bandit-config-generator -t B201,B301 -s B101 > bandit.yaml

Inline suppression with # nosec

Mark a line to suppress all findings on it:

self.proc = subprocess.Popen('/bin/sh', shell=True)  # nosec

Suppress specific test IDs (other findings on the line are still reported):

self.proc = subprocess.Popen('/bin/ls *', shell=True)  # nosec B602, B607

Use the test name instead of ID:

assert yaml.load("{}") == []  # nosec assert_used

Best practice: Always add a comment explaining why the suppression is justified:

# The hash here is not in a security context — collisions are acceptable.
the_hash = md5(data).hexdigest()  # nosec B303

Baseline workflow

Use a baseline to track only new issues introduced since a reference point. Useful in CI to avoid noise from pre-existing findings.

# 1. Generate a baseline from the current codebase (JSON format required)
bandit -r . -f json -o baseline.json

# 2. Commit baseline.json to the repo

# 3. In CI, compare against baseline — only new issues cause failure
bandit -r . --baseline baseline.json

Commit the baseline when you intentionally accept existing issues.

Pre-commit integration

Add to .pre-commit-config.yaml:

repos:
  - repo: https://github.com/PyCQA/bandit
    rev: '1.8.5'   # pin to a real release tag
    hooks:
      - id: bandit

With a pyproject.toml config:

repos:
  - repo: https://github.com/PyCQA/bandit
    rev: '1.8.5'
    hooks:
      - id: bandit
        args: ["-c", "pyproject.toml"]
        additional_dependencies: ["bandit[toml]"]

CI/CD example (GitHub Actions)

- name: Run Bandit
  run: |
    pip install "bandit[toml]"
    bandit -r src/ -c pyproject.toml -f json -o bandit-results.json
  continue-on-error: false

For GitHub code scanning (SARIF upload):

- name: Run Bandit (SARIF)
  run: |
    pip install "bandit[sarif]"
    bandit -r . -f sarif -o bandit.sarif

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: bandit.sarif

Key plugin test IDs

See references/plugins.md for the full catalogue. Critical ones to know:

IDNameWhat it catchesSeverity
B101assert_usedassert statements (stripped in -O mode)LOW
B102exec_usedexec() built-inMEDIUM
B104hardcoded_bind_all_interfaces0.0.0.0 as bind addressMEDIUM
B105/6/7hardcoded_password_*Hardcoded passwords in strings/args/defaultsLOW
B110try_except_passexcept: pass silences errorsLOW
B201flask_debug_trueapp.run(debug=True)HIGH
B301picklepickle.loads, dill, shelve, jsonpickleMEDIUM
B303md5hashlib.md5, hashlib.sha1 (non-security context)MEDIUM
B307evaleval() usageMEDIUM
B311randomrandom.random() etc. for security useLOW
B324hashlibhashlib.new('md5', ...) with insecure algoMEDIUM
B401import_telnetlibimport telnetlibHIGH
B501request_with_no_cert_validationverify=False in requestsHIGH
B506yaml_loadyaml.load() without LoaderMEDIUM
B602subprocess_popen_with_shell_truesubprocess.Popen(..., shell=True)HIGH
B608hardcoded_sql_expressionsString-formatted SQL queriesMEDIUM
B701jinja2_autoescape_falseJinja2 autoescape disabledHIGH

Common pitfalls & how to handle them

B101 false positives in test files

assert is essential in pytest. Skip B101 for the test directory:

bandit -r . -s B101    # skip globally
# or exclude the tests dir entirely
bandit -r src/         # only scan source, not tests

Or in config: skips = ["B101"]

B311 (random) in non-security contexts

random is fine for simulations, games, shuffling display order. Suppress with # nosec B311 and explain why. Use secrets module for tokens, passwords, session IDs.

B506 (yaml.load)

Always use yaml.safe_load() or yaml.load(data, Loader=yaml.SafeLoader) instead of bare yaml.load().

B602 / B603 (subprocess shell)

Prefer subprocess.run(["cmd", "arg"]) (list form, shell=False) over subprocess.run("cmd arg", shell=True). Shell=True + user input = shell injection.

B324 vs B303

B303 fires on hashlib.md5() / hashlib.sha1(). B324 fires on hashlib.new('md5'). Both flag insecure hashes. For non-security uses (checksums, cache keys), suppress with # nosec B303 or # nosec B324.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.