Appearance
Contributing to NetVuln Tool
Thank you for your interest in contributing. This guide covers the conventions and workflows for the netvuln-tool repository.
Getting started
Clone and set up
bash
# Clone the repository (SSH on port 2222)
git clone ssh://git@100.101.73.49:2222/Bullium-Consulting/netvuln-tool.git
cd netvuln-tool
# Set up the development environment (git hooks, verify dependencies)
bash setup.shsetup.sh configures the git hooks (pre-commit: ShellCheck plus mypy on staged files; pre-push: pytest plus BATS) and verifies that the required dependencies are installed.
Dependencies
- Required: nmap, bash, coreutils, jq
- Optional: wkhtmltopdf (PDF export), mail/sendmail (email features)
- Optional (Linux only):
iw,nmcli(managed-mode WiFi discovery),aircrack-ng(opt-in monitor capture) - Testing: bats-core (BATS), Node.js plus npm (client-side JS tests), Python 3 (pytest plus mypy)
- Platforms: macOS (development) and Linux/Debian (deployment, including Raspberry Pi)
Code style
Bash scripts
- File naming: underscores only,
my_script.sh(nevermy-script.sh). - Strict mode: every script begins with
set -euo pipefail. - Functions: descriptive names in
snake_case. - Variables:
UPPER_CASEfor constants,lower_casefor locals. - Linting: all scripts must pass
shellcheckbefore commit. - Library functions: use the
nv_*prefix (lib/netvuln_common.sh) or theet_*prefix (lib/exec_template.sh). - Header comments: include purpose, author, version, and usage.
Shell template
bash
#!/bin/bash
# SPDX-License-Identifier: Apache-2.0
# Copyright 2024-2026 Bullium Consulting
###############################################################################
# Script Name: example_script.sh
# Description: Brief description of what this script does
# Author: Your Name (Bullium Consulting) <email@bullium.com>
# Version: X.Y.Z
###############################################################################
set -euo pipefail
# Source the shared library
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/netvuln_common.sh"
# ... script body ...Linting
All scripts must pass ShellCheck before commit:
bash
shellcheck scripts/*.sh
shellcheck lib/netvuln_common.shThe pre-commit hook runs ShellCheck automatically on staged .sh files.
Branching strategy
main: stable releases only.dev: integration branch for active development.feature/*: new features (branch fromdev).bugfix/*: bug fixes (branch fromdev).
Never commit directly to main. Always branch from dev.
Workflow
- Create a branch from
dev:git checkout -b feature/my-feature dev. - Make changes and commit using the conventional format.
- Push the branch and open a pull request on Gitea targeting
dev. - After CI passes and the PR is approved, squash-merge to
dev. - Release: open a PR from
devtomain;release_check.ymlenforces the version bump; merging tagsvX.Y.Zand creates a Gitea Release. - Sync:
git checkout dev && git merge main && git push origin dev.
Test-driven development
Follow Red-Green-Refactor: write a failing test first, watch it fail for the expected reason, write the minimal code to pass, then refactor. Run the full suite before opening a PR.
Issue-tracked workflow
Non-trivial bugs and features are tracked as Gitea issues. Search existing issues before coding; open one before writing code if none covers it; name the branch after the issue (fix/123-short-slug); reference it in commits (fix: dedupe rows (#123)); and include Closes #123 in the PR so the merge auto-closes it. Each issue records estimated plus actual effort via Gitea native time tracking.
Commit messages
Use conventional commits:
feat: add network discovery module
fix: correct CIDR validation edge case
docs: update API contract documentation
test: add BATS tests for upload scripts
chore: update shellcheck configuration
refactor: extract common validation functionsNo AI attribution
Commit messages must not include AI attribution or generation markers (no Co-Authored-By, no "Generated with ..." lines). Keep messages clear, descriptive, and focused on the technical change.
Testing
The suite totals 1,667 tests: 1,088 BATS tests for the shell scripts, 143 vitest tests for the report template JavaScript, and 436 pytest tests for the Python orchestrator.
bash
# All BATS tests
bats tests/
# Client-side JS tests (report template)
npm run test:client
# Python orchestrator tests
python3 -m pytest tests/python/
# Strict mypy on the netvuln/ package
python3 -m mypy netvuln/
# Lint the BATS assertion convention (also runs in CI and pre-commit)
bash scripts/check_bats_assertions.sh
# A specific suite
bats tests/test_push_session.batsInstall BATS with brew install bats-core (macOS) or sudo apt-get install -y bats (Debian/Ubuntu). The client-side tests extract the JavaScript embedded in report_template.sh and run it in jsdom via vitest; install Node dependencies with npm install.
BATS assertion convention
bats detects a mid-test failure through bash errexit plus an ERR trap. On bash older than 4.1 (notably the macOS /bin/bash 3.2 that ships on a stock Mac), neither reacts to a failing compound command, so a bare standalone [[ ... ]] or (( ... )) assertion that is not the last command of a test silently passes when it fails. This is a documented upstream gotcha, not a bats bug, and no bats upgrade fixes it.
Rules for tests/*.bats:
Append
|| falseto every standalone[[ ... ]]or(( ... ))assertion, including the final one:bash[[ "$output" == *"expected"* ]] || false (( count == 3 )) || false[ ... ],grep -q, helper functions, andrunfollowed by[ "$status" -eq 0 ]are simple commands; they are detected on every bash version and need no guard.Side-effect arithmetic such as
(( i++ ))must use|| trueinstead (a post-increment from 0 returns nonzero and would abort the test on bash 4+).
scripts/check_bats_assertions.sh flags violations and runs in the CI bats job and the pre-commit hook. tests/test_meta_bats_detection.bats is a canary that fails loudly if the bats/bash combination ever stops reporting mid-test failures.
License
This project is licensed under the Apache License 2.0, except for the proprietary appliance/ subtree (see Open Source Boundary).
By contributing, you agree that your contributions will be licensed under the Apache License 2.0 that covers this project. You also certify that you have the right to submit the work under this license, per the Developer Certificate of Origin (DCO).
SPDX headers
All new scripts must include the SPDX license identifier after the shebang line:
bash
#!/bin/bash
# SPDX-License-Identifier: Apache-2.0
# Copyright 2024-2026 Bullium ConsultingQuestions?
Open an issue on the repository or contact support@bullium.com.
