Skip to content

Commit 8527cfb

Browse files
authored
chore: Added bandit pre-commit hook (hiero-ledger#2324)
Signed-off-by: Manish Dait <daitmanish88@gmail.com>
1 parent 51b6d5c commit 8527cfb

16 files changed

Lines changed: 888 additions & 595 deletions

File tree

.codacy.yml

Lines changed: 0 additions & 13 deletions
This file was deleted.

.pre-commit-config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,10 @@ repos:
1313
hooks:
1414
- id: ruff-check
1515
- id: ruff-format
16+
- repo: https://github.com/PyCQA/bandit
17+
rev: 1.9.4
18+
hooks:
19+
- id: bandit
20+
args: ["-c", "bandit.yml", "-ll"]
21+
files: ^(src|tck)/
22+
verbose: true

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ We welcome blog posts! Whether you're sharing a tutorial, case study, or your ex
107107
| [Merge Conflicts](https://github.com/hiero-ledger/sdk-collaboration-hub/blob/main/guides/issue-progression/for-developers/merge_conflicts.md) | Resolving conflicts |
108108
| [Types](docs/sdk_developers/types.md) | Python type hints |
109109
| [Linting](docs/sdk_developers/ruff.md) | Code quality tools |
110+
| [Security Analysis](docs/sdk_developers/bandit.md) | Security analysis & vulnerability scanning |
110111

111112
---
112113

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77

88
A Python SDK for interacting with the Hedera Hashgraph platform.
99

10-
>**Python compatibility:**
10+
> [!NOTE]
11+
>**Python compatibility**
12+
>
1113
> The SDK supports Python ≥ 3.10 and is tested on Python 3.10–3.14. Newer Python versions may work but have not yet been validated.
1214
1315
## Quick Start
@@ -74,6 +76,7 @@ print(f"Balance: {balance.hbars} HBAR")
7476
- **[Merge Conflicts Guide](https://github.com/hiero-ledger/sdk-collaboration-hub/blob/main/guides/issue-progression/for-developers/merge_conflicts.md)** - Resolve conflicts
7577
- **[Typing Guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/types.md)** - Python type hints
7678
- **[Linting Guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/ruff.md)** - Code quality tools
79+
- **[Security Analysis](docs/sdk_developers/bandit.md)** - Security analysis & vulnerability scanning
7780

7881
### Hedera Network Resources
7982

bandit.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
exclude_dirs: ['.clusterfuzzlite/**']
2+
3+
assert_used:
4+
skips:
5+
- '**/tests/**/*.py'

docs/sdk_developers/bandit.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Bandit
2+
3+
This README provides an introduction to using Bandit with the Hiero Python SDK. We use uv to manage the environment and Bandit to handle static security analysis and vulnerability scanning.
4+
5+
## What Is Bandit?
6+
7+
[Bandit](https://bandit.readthedocs.io/en/latest/) is a security-focused static analysis tool designed to find common security vulnerabilities and flaws in Python code.
8+
9+
## 🎯 Why Use Bandit?
10+
11+
**Vulnerability Detection:** Catches critical security flaws like hardcoded passwords, shell injections, weak cryptography, and unsafe serialization.
12+
13+
**Fine-Grained Severity Rules:** Categorizes threats into Low, Medium, and High severities to establish structural pass/fail criteria.
14+
15+
16+
## ⚙️ Installation
17+
18+
We use **uv** to manage the Hiero Python SDK environment. Bandit is included in the `lint` dependency group.
19+
20+
### The Recommended Way (Using uv)
21+
The below command will simply pull down the latest dependencies and synchronize your local environment in one step:
22+
```bash
23+
uv sync
24+
```
25+
26+
### Alternative Installation Layouts
27+
28+
If you need to install Bandit manually into an alternate isolated setup or are using a different environment manager, use the corresponding configuration below:
29+
```bash
30+
# Explicitly add to the development group via uv
31+
uv add --group lint bandit
32+
33+
# Using classic pip inside an active virtualenv
34+
pip install bandit
35+
36+
# Using Poetry
37+
poetry add --group lint bandit
38+
39+
# Using Conda
40+
conda install -c conda-forge bandit
41+
```
42+
> [!TIP]
43+
> Make sure `bandit` is available in the same virtual environment (`.venv`) you use to run the Hiero SDK. If using **uv**, simply running `uv sync` will set everything up for you automatically.
44+
45+
## ▶️ Usage
46+
47+
### Manual Checking for vulnerabilities
48+
49+
We run security checks against our package source paths and active development scripts.
50+
51+
```bash
52+
# Check the entire source directory recursively
53+
uv run bandit -c bandit.yml -r src/
54+
55+
# Check multiple active development folders together
56+
uv run bandit -c bandit.yml -r src/ tck/ tests/
57+
58+
# Run with custom thresholds
59+
uv run bandit -c bandit.yml -l -r src/
60+
61+
# Run checks and generate a clean text log report file
62+
uv run bandit -c bandit.yml -r src/ --format txt --output bandit_report.txt
63+
```
64+
65+
### Run using Pre-Commit Hook
66+
67+
If you want to run the Bandit using the `pre-commit` configuration, use:
68+
69+
```bash
70+
uv run pre-commit run --all-files
71+
```
72+
73+
## 🛠️ Handling Security Issues
74+
75+
### How Severity Levels Affect Commits
76+
Unlike code formatters, Bandit will never modify your code automatically. Security risks must be reviewed and patched manually based on their tier:
77+
78+
- **Low Severity (Warnings):** Issues like public parameter keywords triggering hardcoded credential filters (`B106`) or standard pseudo-random generators (`B311`) or any other low severity issue will print out to your logging metrics for context but will not block your commit.
79+
80+
An example of a passing run containing a low-severity warning:
81+
```
82+
Test results:
83+
No issues identified.
84+
85+
Code scanned:
86+
Total lines of code: 24726
87+
Total lines skipped (#nosec): 0
88+
89+
Run metrics:
90+
Total issues (by severity):
91+
Undefined: 0
92+
Low: 1
93+
Medium: 0
94+
High: 0
95+
```
96+
97+
- **Medium & High Severity (Blockers):** High-risk flaws like deprecated cryptographic libraries (`B413`), exposed keys, or command injections throw a failure execution code and instantly halt your commit.
98+
99+
### Inline Suppressions (`# nosec`)
100+
101+
Sometimes an abstract pattern triggers a false positive that has been reviewed and verified as safe. You can silence individual lines using the inline `# nosec` statement followed by the specific issue ID.
102+
103+
```python
104+
# Suppress alerts for executing a fixed, safe system command
105+
import subprocess
106+
subprocess.Popen(["/bin/ls", "-l"], shell=False) # nosec B602, B607
107+
108+
# Tell Bandit this specific assert statement is intentional and safe
109+
assert user_role == "admin" # nosec B101
110+
```
111+
112+
### Targeted Rule Suppressions
113+
Instead of disabling a rule globally or littering your files with `# nosec` comments, you can use Bandit's plugin-specific configuration blocks to skip rules for matching file patterns.
114+
115+
```yml
116+
# bandit.yml
117+
118+
# Global directory exclusions
119+
exclude_dirs: ['.clusterfuzzlite/**']
120+
121+
# Targeted plugin rule overrides
122+
assert_used:
123+
skips:
124+
- '**/tests/**/*.py'
125+
126+
exec_used:
127+
skips:
128+
- '**/tests/mocks/**/*.py'
129+
```
130+
131+
**Global Suppressions:** If a specific rule is completely irrelevant to entire codebase, do not add `# nosec` everywhere. Instead, permanently drop it by adding the error code to the `skips` list inside `bandit.yml` file.
132+
133+
```yml
134+
skips: ["B101", "B601", "B413"]
135+
```
136+
137+
## 📝 Example Output
138+
139+
### When structural vulnerabilities are found:
140+
141+
If Bandit discovers a violation that meets or exceeds your active severity threshold (Medium or High), it halts execution, rejects the commit, and provides a detailed breakdown including the issue ID, line numbers, and its Common Weakness Enumeration (CWE) classification:
142+
143+
```text
144+
Run started: 2026-05-31 18:00:20.408359+00:00
145+
146+
Test results:
147+
>> Issue: [B602:subprocess_popen_with_shell_equals_true] subprocess call with shell=True identified, possible injection.
148+
Severity: High Confidence: High
149+
CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
150+
Location: src/example_module/utils.py:12:4
151+
11 def execute_user_query(user_input):
152+
12 subprocess.Popen(user_input, shell=True)
153+
13
154+
155+
--------------------------------------------------
156+
Code scanned:
157+
Total lines of code: 23318
158+
Run metrics:
159+
Total issues (by severity): Low: 3, Medium: 0, High: 1
160+
```
161+
162+
### When security scans clear successfully:
163+
164+
If project satisfies active gating baseline, it finishes with a clean summary report:
165+
```text
166+
bandit...................................................................Passed
167+
168+
Test results:
169+
No issues identified.
170+
171+
Code scanned:
172+
Total lines of code: 23318
173+
Total lines skipped (#nosec): 2
174+
175+
Run metrics:
176+
Total issues (by severity):
177+
Undefined: 0
178+
Low: 0
179+
Medium: 0
180+
High: 0
181+
```
182+
183+
Happy scanning! 🛡️

docs/sdk_developers/pr_review_guidelines.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ AI-assisted review tools can be helpful but require critical thinking:
197197
| [Submitting a Pull Request](training/workflow/10_submit_pull_request.md) | Step-by-step PR submission details |
198198
| [Signing Requirements](training/workflow/07_signing_requirements.md) | GPG and DCO commit signing |
199199
| [Linting Guide](ruff.md) | Code quality with Ruff |
200+
| [Security Analysis](bandit.md) | Security analysis & vulnerability scanning |
200201

201202
### Need Help?
202203

docs/sdk_developers/ruff.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ poetry add --dev ruff
3434
# Using Conda
3535
conda install -c conda-forge ruff
3636
```
37-
>**TIP!**
37+
>[!TIP]
3838
>Make sure `ruff` is available in the same virtual environment (`.venv`) you use to run the Hiero SDK. If using **uv**, simply running `uv sync` will set everything up for you automatically.
3939
4040

@@ -131,7 +131,6 @@ Each error has a code. You can look up the full details of any code in the [Ruff
131131
**When issues are found:**
132132

133133
If Ruff detects violations, it provides the file path, line number, and a specific error code (e.g., ARG001 or I001).
134-
Plaintext
135134

136135
```text
137136
src/hiero_sdk_python/tokens/nft_id.py:14:4: ARG001 Unused function argument: `tokenId`

docs/sdk_developers/setup.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,14 @@ uv sync --dev --all-extras
178178

179179
## Pre-Commit Tool Setup
180180

181-
To maintain high code quality and security, this repository uses `re-commit` hooks. These hooks automatically run checks (like `Ruff` for linting and `Gitleaks` for security) every time you attempt to commit code.
181+
To maintain high code quality and security, this repository uses `pre-commit` hooks. These hooks automatically run checks (like `Ruff` for linting, `Bandit` for static security analysis and `Gitleaks` for security) every time you attempt to commit code.
182182

183183
### Installation
184184
---
185185

186186
**Option 1: Using `uv` (Recommended)**
187187

188-
`uv` is recommended because it manages pre-commit within your project’s locked environment, ensuring your local linting matches the CI exactly.
188+
`uv` is recommended because it manages pre-commit within your project’s locked environment, ensuring your local changes matches the CI exactly.
189189

190190
1. **Install the git hooks:**
191191
```bash
@@ -213,7 +213,7 @@ pre-commit install
213213

214214
Once installed, `git commit` will automatically trigger the checks.
215215
- If they **pass**: Your commit is created normally.
216-
- If they **fail**: The hooks will often fix the files for you (e.g., `Ruff` reformatting). Simply `git add` the changed files and commit again.
216+
- If they **fail**: Some hooks may auto-fix files (e.g., `Ruff` formatting). Others (e.g., `Bandit`) only report findings that you must fix manually, then `git add` and commit again.
217217

218218

219219
### Manual Execution

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ lint = [
5656
"ruff>=0.14.9,<1",
5757
"mypy>=1.18.2,<3",
5858
"typing-extensions>=4.15.0,<5",
59+
"bandit>=1.8.2,<2"
5960
]
6061

6162
[tool.uv]

0 commit comments

Comments
 (0)