Skip to content

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.sh

setup.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 (never my-script.sh).
  • Strict mode: every script begins with set -euo pipefail.
  • Functions: descriptive names in snake_case.
  • Variables: UPPER_CASE for constants, lower_case for locals.
  • Linting: all scripts must pass shellcheck before commit.
  • Library functions: use the nv_* prefix (lib/netvuln_common.sh) or the et_* 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.sh

The 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 from dev).
  • bugfix/*: bug fixes (branch from dev).

Never commit directly to main. Always branch from dev.

Workflow

  1. Create a branch from dev: git checkout -b feature/my-feature dev.
  2. Make changes and commit using the conventional format.
  3. Push the branch and open a pull request on Gitea targeting dev.
  4. After CI passes and the PR is approved, squash-merge to dev.
  5. Release: open a PR from dev to main; release_check.yml enforces the version bump; merging tags vX.Y.Z and creates a Gitea Release.
  6. 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 functions

No 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.bats

Install 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 || false to every standalone [[ ... ]] or (( ... )) assertion, including the final one:

    bash
    [[ "$output" == *"expected"* ]] || false
    (( count == 3 )) || false
  • [ ... ], grep -q, helper functions, and run followed 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 || true instead (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 Consulting

Questions?

Open an issue on the repository or contact support@bullium.com.

Apache-2.0 licensed (appliance subtree proprietary)