@codacy/tools-bandit-1
v0.24.0
Published
Bandit adapter — CLI-mode Python security linter
Readme
@codacy/tools-bandit-1
Table of Contents
Overview
Python security linter using the Bandit binary. Uses the CLI execution strategy -- spawns bandit from a managed Python venv via spawnTool() and parses its JSON output.
| Property | Value |
| ------------- | -------------------------------------- |
| Tool ID | Bandit |
| Codacy UUID | 89b6fc6a-9137-4cf3-8b9f-dcc3bedfa738 |
| Strategy | CLI |
| Languages | Python |
| Binary | bandit (pip-installed in venv) |
| File patterns | **/*.py |
Updating patterns
# Re-fetch pattern metadata from the Codacy API
pnpm prefetch
# Commit the result
git add src/patterns.jsonPattern IDs follow the format Bandit_B602, Bandit_B301, etc.
Updating the Bandit version
- Update
preferredVersioninsrc/adapter.ts - Update the
PIP_PACKAGESarray with the new pinned version - Run
pnpm prefetchto check for new/removed rules - Run
pnpm testto verify compatibility - If the major version changes, create a new adapter package (
bandit-2/)
Development
pnpm build # Build with tsup
pnpm test # Run tests (requires bandit in PATH or venv)To install bandit locally for testing:
pip install bandit==1.8.3Notes for maintainers
Preset mappings (
src/pattern-mappings.json): 18 of the 78 checks are gated on a detected PyPI dependency, because they only ever fire against one library's API. Ten were default-on and now stay out of a repo that does not declare the library —B201(Flask),B701(Jinja2),B702(Mako),B601(Paramiko),B320/B410(lxml),B506(PyYAML),B113/B501(requests) andB308(Django). Eight were default-off and are now reachable at all:B610/B611/B703(Django SQLi/XSS),B507(Paramiko host keys),B508/B509(PySNMP),B413/B414(PyCrypto vs. PyCryptodome — separate projects, so separate entities). Left universal on purpose: the stdlib checks (B301–B307,B324) andB412, whose httpoxy CGI handler has no manifest to read.Two of these need a second key, because gating gets its evidence from direct declarations only:
B701is claimed byflaskas well asjinja2. Flask hard-depends on Jinja2 (Flask→jinja2>=3.1.2), so a real Flask app usually never lists Jinja2 itself, and gating onjinja2alone dropped a High-severity autoescape check from most Flask repos.B501is claimed byhttpxas well asrequests. Bandit's owncrypto_request_no_cert_validationplugin inspects both libraries, so an httpx-only repo would otherwise lose theverify=Falsecheck.
Three of these gates are inert, and deliberately kept anyway:
B320,B410(lxml) andB414(pycryptodome) are still in Codacy's pattern catalog but Bandit 1.8.3 no longer registers the checks, so they can never fire (blacklists/calls.py: "skipped B320 as the check for a call to lxml.etree has been removed";blacklists/imports.py: the same forB410;B414is simply absent fromgen_blacklist()).mapping-drift.test.tscannot see this — it compares against Codacy's catalog, not the installed tool. Dropping the mappings would make three default-on High/Security patterns universal again and write them into every Python repo's config, so the gate is the lesser evil until the catalog catches up. Seedocs/tech-debt.md.Bandit requires Python 3 as a runtime. The adapter uses an isolated venv at
~/.codacy/runtimes/bandit-1/venv/.Exit code 0 = no findings, 1 = findings found (normal), >1 = error.
col_offsetin bandit output is 0-based; the adapter adds 1 for the 1-based Issue model.Bandit's
issue_confidence(LOW/MEDIUM/HIGH) maps to numeric confidence (1/2/3) on the Issue.CWE information from
issue_cweis appended to the issue message as(CWE-{id}).Config file detection supports
.bandit(INI, passed with--ini),bandit.yml(YAML, passed with-c), andpyproject.toml(TOML, passed with-c).Pattern filtering uses the
-tflag to pass comma-separated test IDs to bandit.The
errorsarray in bandit's JSON output (file-level errors like syntax errors) is mapped toAnalysisErrorobjects with level "warning".
