diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml
new file mode 100644
index 0000000..58d698c
--- /dev/null
+++ b/.github/workflows/bandit.yml
@@ -0,0 +1,27 @@
+---
+name: Bandit Security Scan
+
+on:
+ push:
+ branches: ["master"]
+ pull_request:
+ branches: ["master"]
+ schedule:
+ - cron: "0 0 * * 0"
+ workflow_dispatch:
+
+jobs:
+ analyze:
+ runs-on: ubuntu-latest
+ permissions:
+ security-events: write
+ env:
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6.0.2
+
+ - name: Perform Bandit Analysis
+ uses: PyCQA/bandit-action@v1
+ with:
+ targets: "bitmath/ tests/"
diff --git a/CLAUDE.md b/CLAUDE.md
index 6830ee3..8abd675 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -27,11 +27,14 @@ Phases 1 (maintenance 1.4.0) and 2 (bitmath 2.0.0) are complete. The project:
## Common Commands
```bash
-# Run the full test suite with coverage (creates venv, runs pytest + linting)
+# Run the full test suite with coverage (creates venv, runs pytest + linting + bandit)
make ci
+# Run security scan only
+make ci-bandit
+
# Run linting only
-ruff check bitmath/ tests/
+make ci-pylint
# Build a wheel
make build
@@ -66,6 +69,14 @@ All unit values are normalized to bits internally; conversion between units happ
**Constants:** `NIST`, `SI`, `NIST_PREFIXES`, `SI_PREFIXES`, `ALL_UNIT_TYPES`
+## Versioning
+
+The single source of truth for the version is the `VERSION` file. `pyproject.toml` reads it dynamically via `[tool.hatch.version]` — do not edit the version in `pyproject.toml` directly. The `Makefile` also reads `VERSION` for docs, man pages, and RPM builds. To bump the version, edit `VERSION` only.
+
+## Security Scanning
+
+Bandit runs as part of `make ci` via the `ci-bandit` target, scanning both `bitmath/` and `tests/`. It also runs as a GitHub Actions workflow (`.github/workflows/bandit.yml`) on push/PR to master and weekly. No issues were present as of 2.0.2.
+
## Testing Notes
- Test runner: `pytest`
diff --git a/Makefile b/Makefile
index 43e53de..698f730 100644
--- a/Makefile
+++ b/Makefile
@@ -216,5 +216,12 @@ ci-pylint:
@echo "#################################################"
. $(NAME)env3/bin/activate && pylint bitmath/__init__.py
-ci: clean uniquetestnames virtualenv ci-list-deps ci-pycodestyle ci-pylint ci-unittests
+ci-bandit:
+ @echo ""
+ @echo "#############################################"
+ @echo "# Running Bandit Security Scan in virtualenv"
+ @echo "#############################################"
+ . $(NAME)env3/bin/activate && bandit -r -v bitmath/ tests/
+
+ci: clean uniquetestnames virtualenv ci-list-deps ci-pycodestyle ci-pylint ci-bandit ci-unittests
:
diff --git a/README.rst b/README.rst
index 27b2ff6..7053f93 100644
--- a/README.rst
+++ b/README.rst
@@ -7,6 +7,10 @@
.. image:: https://github.com/timlnx/bitmath/actions/workflows/python.yml/badge.svg
:target: https://github.com/timlnx/bitmath/actions/workflows/python.yml
+.. image:: https://github.com/timlnx/bitmath/actions/workflows/bandit.yml/badge.svg
+ :target: https://github.com/timlnx/bitmath/actions/workflows/bandit.yml
+ :alt: Bandit Security Scan
+
.. image:: https://img.shields.io/github/issues/timlnx/bitmath?style=flat-square
:target: https://github.com/timlnx/bitmath/issues
:alt: Open issues
@@ -15,6 +19,10 @@
:target: https://github.com/timlnx/bitmath/pulls
:alt: Open pull requests
+.. image:: https://img.shields.io/pypi/v/bitmath.svg
+ :target: https://pypi.org/project/bitmath/
+ :alt: Latest Version
+
.. image:: https://img.shields.io/pypi/dm/bitmath?style=flat-square
:target: https://pypistats.org/packages/bitmath
:alt: PyPI - Package Downloads
@@ -23,9 +31,9 @@
:target: https://pypistats.org/packages/bitmath
:alt: GitHub Project Popularity
-.. image:: https://img.shields.io/pypi/l/bitmath?style=flat-square
- :target: https://opensource.org/licenses/MIT
- :alt: PyPI - License
+.. image:: https://img.shields.io/badge/license-MIT-blue.svg
+ :target: https://github.com/timlnx/bitmath/blob/master/LICENSE
+ :alt: License
.. image:: https://img.shields.io/pypi/implementation/bitmath?style=flat-square
:alt: PyPI - Implementation
diff --git a/VERSION b/VERSION
index 38f77a6..e9307ca 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.1
+2.0.2
diff --git a/bitmath.1 b/bitmath.1
index 3bbd11f..461069d 100644
--- a/bitmath.1
+++ b/bitmath.1
@@ -2,12 +2,12 @@
.\" Title: bitmath
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot
-.\" Date: 05/04/2026
+.\" Date: 05/05/2026
.\" Manual: python-bitmath
-.\" Source: bitmath 2.0.1
+.\" Source: bitmath 2.0.2
.\" Language: English
.\"
-.TH "BITMATH" "1" "05/04/2026" "bitmath 2\&.0\&.1" "python\-bitmath"
+.TH "BITMATH" "1" "05/05/2026" "bitmath 2\&.0\&.2" "python\-bitmath"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/pyproject.toml b/pyproject.toml
index 2749282..c729a41 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "bitmath"
-version = "2.0.1"
+dynamic = ["version"]
description = "Pythonic module for representing and manipulating file sizes with different prefix notations (file size unit conversion)"
readme = "README.rst"
requires-python = ">=3.9"
@@ -78,6 +78,10 @@ exclude = [
[tool.hatch.build.targets.wheel]
packages = ["bitmath"]
+[tool.hatch.version]
+path = "VERSION"
+pattern = '(?P.+)'
+
[tool.hatch.publish.index]
disable = true
diff --git a/requirements.txt b/requirements.txt
index 8e4bceb..e5acdd0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+bandit
pycodestyle
pylint
pytest