| layout | default |
|---|---|
| title | Contributing |
We welcome contributions! Please read this guide to understand how you can contribute.
See the Code of Conduct.
- 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 (plain go mod tidy), then confirm the go directive is still go 1.26.0.
The toolchain line is separate: it names the patched Go release that builds
from source use (#243). With the default GOTOOLCHAIN=auto, an older local Go
downloads that release, so go install and source builds of the action never
ship the original 1.26.0 standard library, which has since had security fixes.
Raise it to the newest 1.26.x when a Go patch release comes out; it never
changes the go 1.26.0 language floor.
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 the current Go release (1.27; the module supports 1.26 and later) 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.
- 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
The project includes a Makefile to simplify development tasks:
# Build the binary
make build
# Run tests (go test -v ./..., without the race detector; see Testing Requirements)
make test
# Run linter
make lint
# Tidy modules: runs go mod tidy; then confirm the go directive is still go 1.26.0
make tidy
# Clean up build artifacts
make clean
# Run a safe simulated scan (live scans need: make run DOMAIN=yourdomain.com)
make simulateYou can use Docker for development to ensure a consistent environment:
# Build the Docker image
make docker-build
# Simulated scan in a container (no DNS traffic)
make docker-simulate
# Live scan in a container: name a domain you own or may test
make docker-run DOMAIN=yourdomain.com-
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 with the race detector, as CI does (see Testing Requirements), and lint them:
go test -race ./... make lintThe race detector needs cgo and a C toolchain. If you have none, run
make testlocally; CI still runs the suite with-race. -
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
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
- 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.
- 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.
Use -simulate to develop and test without making real DNS queries:
./subenum -simulate -hit-rate 30 -w examples/sample_wordlist.txt example.comThis lets you iterate on output formatting, flag handling, and new features safely.
All pull requests must pass the full test suite, including the race detector:
go test -v -race ./...On Windows, Go 1.26.0 reports false data races (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. You need no
workaround: go.mod names toolchain go1.26.11, so a local Go older than
that switches to the patched toolchain by itself. The problem only comes
back if you force Go 1.26.0 with GOTOOLCHAIN=local.
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.
Parsers of untrusted input have fuzz targets (grep -rn "^func Fuzz" .): the
Wayback answer, lab scenarios, domain and wordlist normalisation, MCP request
lines, and zone-transfer and DNSSEC denial messages. go test runs their seed
inputs; to fuzz one, name it and its package:
go test -run '^$' -fuzz '^FuzzHostNames$' -fuzztime 1m ./internal/passive/A failing input is saved under the package's testdata/fuzz/; commit it with
the fix so it stays a regression test.