Contributing to subenum
We welcome contributions! Please read this guide to understand how you can contribute.
See the Code of Conduct.
Development Environment Setup
Prerequisites
- Go 1.26 or later
- Git
- Make (optional but recommended)
- Docker (optional, for containerized development)
The go directive in go.mod must stay exactly go 1.26.0. CI fails the build
if it drifts. Current golang.org/x/sys and golang.org/x/text declare
go 1.26.0, so it is also the floor. New dependencies must keep it and pass
govulncheck, which CI runs. On PowerShell, quote -go=1.26.0; unquoted it is
parsed as -go=1. After changing dependencies run make tidy.
Codespaces / Dev Containers
The quickest start needs no local setup. Open the repository in GitHub Codespaces, or use “Reopen in Container” in VS Code. The container in .devcontainer/ comes with Go 1.26 and the CI version of golangci-lint, and builds the binary. make test and ./subenum -simulate example.com then work with no network access to any target.
New here? Look for issues labeled good first issue, and ask questions in Discussions.
Getting Started
- Fork the repository on GitHub
- Clone your fork:
git clone https://github.com/YOUR-USERNAME/subenum.git cd subenum - Set up the upstream remote:
git remote add upstream https://github.com/TMHSDigital/subenum.git
Development Workflow
Using Make
The project includes a Makefile to simplify development tasks:
# Build the binary
make build
# Run tests
make test
# Run linter
make lint
# Tidy modules (keeps the go 1.26.0 pin)
make tidy
# Clean up build artifacts
make clean
# Run a safe simulated scan (live scans need: make run DOMAIN=yourdomain.com)
make simulate
Using Docker
You can use Docker for development to ensure a consistent environment:
# Build the Docker image
make docker-build
# Run the tool in a Docker container
make docker-run
Pull Request Process
- Create a branch for your feature:
git checkout -b feature/your-feature-name -
Make your changes and ensure they follow the project’s coding standards
- Test your changes:
make test make lint -
Commit your changes with a clear message describing the change
- Push to your fork:
git push origin feature/your-feature-name -
Create a pull request to the main repository
- Address any feedback from the code review
Ethical Guidelines
Please ensure that any contributions adhere to the ethical usage principles of this project:
- Features should be designed for educational or legitimate security testing purposes
- Consider potential misuse and implement appropriate safeguards
- Document proper usage scenarios and any necessary warnings
Reporting Bugs
- Search existing issues first to avoid duplicates.
- Open a new issue using the Bug Report template.
- Include:
- The exact command you ran
- Your OS, Go version, and
subenumversion (./subenum -version) - Full terminal output (redact any sensitive domain names)
- Expected vs. actual behaviour
Do NOT include sensitive information, unauthorized scan results, or private domain details.
Suggesting Features
- Search existing issues to avoid duplicates.
- Open a new issue using the Feature Request template.
- Describe:
- The problem the feature solves
- Your proposed solution
- Legitimate security testing use cases it enables
Features that could primarily enable malicious use will be declined.
Simulation Mode for Development
Use -simulate to develop and test without making real DNS queries:
./subenum -simulate -hit-rate 30 -w examples/sample_wordlist.txt example.com
This lets you iterate on output formatting, flag handling, and new features safely.
Testing Requirements
All pull requests must pass the full test suite, including the race detector:
go test -v -race ./...
On Windows, use Go 1.26.3 or later for race runs. Go 1.26.0 reports false
data races there (between context.WithTimeout and the net package’s DNS
lookup goroutine) and can crash with Exception 0xc0000005 in scan.Run;
neither is a bug in subenum, and Linux, where CI runs -race, is not
affected. go.mod keeps go 1.26.0 as the minimum, so pick the toolchain
per command:
GOTOOLCHAIN=go1.26.3 go test -race ./...
New features should include tests. New flags must be covered by at least one test case.
Do not hit public resolvers. Use -simulate or the in-process DNS server in
internal/dnstest, which answers from a per-query handler (records, RCODE,
NODATA, delay, drop, truncation) and counts every query per name and type.
internal/dns tests can also use the table-driven startTestDNS wrapper in
internal/dns/testdns_test.go. The optional live smoke test is gated on
SUBENUM_NETWORK_TESTS=1.