Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Python security vulnerability detection using Bandit SAST with CWE and OWASP mapping. Use when: (1) Scanning Python code for security vulnerabilities and anti-patterns, (2) Identifying hardcoded secrets, SQL injection, command injection, and insecure APIs, (3) Generating security reports with severity classifications for CI/CD pipelines, (4) Providing remediation guidance with security framework references, (5) Enforcing Python security best practices in development workflows.
.claude/skills/aiskillstore-sast-bandit/SKILL.md| Model | Eval pass | Runs |
|---|---|---|
| gemini-3.6-flash | 100% | 87 |
| gemini-3.1-pro-preview | 100% | 1 |
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-09 | ✗→✓ | ▲ Improved | 100% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 111% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 58% | 0% |
| case-22 | ✗→✓ | ▲ Improved | 69% | 0% |
| case-10 | ✓→✓ | = Same ✓ | 67% | 0% |
Bandit is a security-focused static analysis tool for Python that identifies common security vulnerabilities and coding anti-patterns. It parses Python code into Abstract Syntax Trees (AST) and executes security plugins to detect issues like hardcoded credentials, SQL injection, command injection, weak cryptography, and insecure API usage. Bandit provides actionable reports with severity classifications aligned to industry security standards.
Scan a Python file or directory for security vulnerabilities:
bash# Install Bandit pip install bandit # Scan single file bandit suspicious_file.py # Scan entire directory recursively bandit -r /path/to/python/project # Generate JSON report bandit -r project/ -f json -o bandit_report.json # Scan with custom config bandit -r project/ -c .bandit.yaml
Install Bandit via pip:
bashpip install bandit
Create a configuration file .bandit or .bandit.yaml to customize scans:
yaml# .bandit.yaml exclude_dirs: - /tests/ - /venv/ - /.venv/ - /node_modules/ skips: - B101 # Skip assert_used checks in test files tests: - B201 # Flask app run with debug=True - B301 # Pickle usage - B601 # Shell injection - B602 # Shell=True in subprocess
Run Bandit against Python codebase:
bash# Basic scan with severity threshold bandit -r . -ll # Report only medium/high severity # Comprehensive scan with detailed output bandit -r . -f json -o report.json -v # Scan with confidence filtering bandit -r . -i # Show only high confidence findings # Exclude specific tests bandit -r . -s B101,B601
Bandit reports findings with:
Example output:
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: 'admin123'
Severity: Medium Confidence: Medium
CWE: CWE-259 (Use of Hard-coded Password)
Location: app/config.py:12Focus remediation efforts using this priority matrix:
For each finding, consult the bundled references/remediation_guide.md for secure coding patterns. Common remediation strategies:
shell=True, use shlex.split() for argument parsingAdd Bandit to CI/CD pipelines to enforce security gates:
yaml# .github/workflows/security-scan.yml name: Security Scan on: [push, pull_request] jobs: bandit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.11' - name: Install Bandit run: pip install bandit - name: Run Bandit run: bandit -r . -f json -o bandit-report.json - name: Check for high severity issues run: bandit -r . -ll -f txt || exit 1
Use the bundled script scripts/bandit_analyzer.py for enhanced reporting with OWASP mapping.
--no-code flag to exclude code snippets from reports.# nosec comments sparingly and document justifications in code review processes.scripts/)bandit_analyzer.py - Enhanced Bandit wrapper that parses JSON output, maps findings to OWASP Top 10, generates HTML reports, and integrates with ticketing systems. Use for comprehensive security reporting.references/)remediation_guide.md - Detailed secure coding patterns for common Bandit findings, including code examples for SQLAlchemy parameterization, secure subprocess usage, and cryptographic best practices. Consult when remediating specific vulnerability types.cwe_owasp_mapping.md - Complete mapping between Bandit issue codes, CWE identifiers, and OWASP Top 10 categories. Use for security framework alignment and compliance reporting.assets/)bandit_config.yaml - Production-ready Bandit configuration with optimized test selection, exclusion patterns for common false positives, and severity thresholds. Use as baseline configuration for projects.pre-commit-config.yaml - Pre-commit hook configuration for Bandit integration. Prevents commits with HIGH severity findings.Establish security baseline for legacy codebases:
bash# Generate baseline report bandit -r . -f json -o baseline.json # Compare future scans against baseline bandit -r . -f json -o current.json diff <(jq -S . baseline.json) <(jq -S . current.json)
Block merges with HIGH severity findings:
bash# Exit with error if HIGH severity issues found bandit -r . -lll -f txt if [ $? -ne 0 ]; then echo "HIGH severity security issues detected - blocking merge" exit 1 fi
Incrementally increase security standards:
bash# Phase 1: Block only CRITICAL (HIGH severity + HIGH confidence) bandit -r . -ll -i # Phase 2: Block HIGH severity bandit -r . -ll # Phase 3: Block MEDIUM and above bandit -r . -l
Document exceptions inline with justification:
python# Example: Suppressing pickle warning for internal serialization import pickle # nosec B301 - Internal cache, not user input def load_cache(file_path): with open(file_path, 'rb') as f: return pickle.load(f) # nosec B301
scripts/bandit_analyzer.py for enhanced reporting.scripts/bandit_analyzer.py to automatically create Jira/GitHub issues for HIGH severity findings with remediation guidance.Solution:
bandit -r . -i (HIGH confidence only)bandit -r . --exclude /tests/.bandit.yaml to skip specific tests for known safe patterns# nosec comments with justificationSolution:
/venv/, /.venv/, /site-packages/ to .bandit.yaml exclude_dirsgit diff --name-only origin/main | grep '.py$' | xargs banditSolution:
bandit -l (list all tests).bandit.yamlpip install --upgrade banditSolution: Use the bundled assets/pre-commit-config.yaml:
yaml- repo: https://github.com/PyCQA/bandit rev: '1.7.5' hooks: - id: bandit args: ['-ll', '--recursive', '--configfile', '.bandit.yaml']
Install hooks: pre-commit install
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-10 | pass→pass | 14,977 | 12,862 | -14% | 1 | 1 | 0% | 2,924 | 4,892 | +67% | 0 | 0 | — |
case-09 | fail→pass | 15,031 | 16,772 | +12% | 1 | 1 | 0% | 2,690 | 5,377 | +100% | 0 | 0 | — |
case-08 | pass→pass | 11,855 | 7,754 | -35% | 1 | 1 | 0% | 2,096 | 3,898 | +86% | 0 | 0 | — |
case-01 | pass→pass | 16,143 | 15,913 | -1% | 1 | 1 | 0% | 2,817 | 5,322 | +89% | 0 | 0 | — |
case-02 | pass→pass | 9,460 | 4,011 | -58% | 1 | 1 | 0% | 1,713 | 3,041 | +78% | 0 | 0 | — |
case-03 | pass→pass | 12,526 | 5,280 | -58% | 1 | 1 | 0% | 2,319 | 3,248 | +40% | 0 | 0 | — |
case-04 | fail→pass | 7,759 | 3,316 | -57% | 1 | 1 | 0% | 1,375 | 2,895 | +111% | 0 | 0 | — |
case-05 | pass→pass | 8,124 | 3,600 | -56% | 1 | 1 | 0% | 1,539 | 3,000 | +95% | 0 | 0 | — |
case-06 | pass→pass | 4,524 | 2,400 | -47% | 1 | 1 | 0% | 609 | 2,769 | +355% | 0 | 0 | — |
case-07 | pass→pass | 11,906 | 4,685 | -61% | 1 | 1 | 0% | 2,050 | 3,205 | +56% | 0 | 0 | — |
case-11 | pass→pass | 11,796 | 9,160 | -22% | 1 | 1 | 0% | 2,152 | 4,082 | +90% | 0 | 0 | — |
case-12 | pass→pass | 10,512 | 7,001 | -33% | 1 | 1 | 0% | 2,038 | 3,786 | +86% | 0 | 0 | — |
case-13 | pass→pass | 3,460 | 3,908 | +13% | 1 | 1 | 0% | 608 | 2,652 | +336% | 0 | 0 | — |
case-14 | fail→pass | 15,062 | 11,462 | -24% | 1 | 1 | 0% | 2,752 | 4,348 | +58% | 0 | 0 | — |
case-15 | fail→fail | 9,942 | 6,353 | -36% | 1 | 1 | 0% | 1,667 | 3,520 | +111% | 0 | 0 | — |
case-16 | pass→pass | 11,614 | 13,913 | +20% | 1 | 1 | 0% | 2,265 | 4,706 | +108% | 0 | 0 | — |
case-17 | pass→pass | 4,062 | 2,901 | -29% | 1 | 1 | 0% | 671 | 2,869 | +328% | 0 | 0 | — |
case-18 | pass→pass | 7,019 | 5,835 | -17% | 1 | 1 | 0% | 1,274 | 3,386 | +166% | 0 | 0 | — |
case-19 | pass→pass | 8,203 | 9,281 | +13% | 1 | 1 | 0% | 1,575 | 3,945 | +150% | 0 | 0 | — |
case-20 | pass→pass | 9,410 | 8,431 | -10% | 1 | 1 | 0% | 1,630 | 4,007 | +146% | 0 | 0 | — |
case-21 | pass→pass | 13,049 | 11,730 | -10% | 1 | 1 | 0% | 1,003 | 3,349 | +234% | 0 | 0 | — |
case-22 | fail→pass | 13,870 | 8,628 | -38% | 1 | 1 | 0% | 2,315 | 3,903 | +69% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +18 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.