Skip to content

Commit 9d0c56c

Browse files
PR1: subenum 0.5.1 patch (version, race fixes, TUI, build)
Patch-only release. Fixes: - Data race in simulate mode via math/rand/v2 (goroutine-safe, auto-seeded). - Send-on-closed-channel race in scan.Run progress ticker. - TUI Aborted status on ctrl+c; form no longer blocks live mode on empty hit rate. - -version reports v0.5.1. - Docker build copies go.sum / go mod download; base image satisfies module Go version. - Go minimum reconciled to 1.24.2 across go.mod, Dockerfile, README, docs. Added tests: concurrent SimulateResolution, scan runner (concurrent + cancel), TUI form validation. CI: release workflow now also triggers on tag pushes (tags: ['v*']) so the first tag actually builds and publishes binaries. Docs: README facelift; ARCHITECTURE ticker interval (1s) and arg-parsing (cliFlags + flag.*Var) corrected; removed unused docs/assets/title.svg. CHANGELOG and ARCHITECTURE are scoped to 0.5.1 only (no unshipped features). Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent c5b8697 commit 9d0c56c

21 files changed

Lines changed: 291 additions & 67 deletions

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ If applicable, add screenshots or copy the terminal output to help explain your
2525

2626
**Environment (please complete the following information):**
2727
- OS: [e.g. Ubuntu 22.04, Windows 11, macOS 13.0]
28-
- Go Version: [e.g. 1.22.0]
28+
- Go Version: [e.g. 1.24.2]
2929
- subenum Version: [e.g. 0.3.0]
3030

3131
**Additional context**

.github/workflows/go.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name: Go
33
on:
44
push:
55
branches: [ "main" ]
6+
tags: [ "v*" ]
67
pull_request:
78
branches: [ "main" ]
89

.golangci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ linters:
1515
settings:
1616
gosec:
1717
excludes:
18-
# G304: File path provided as taint input expected for a wordlist tool
18+
# G304: File path provided as taint input, expected for a wordlist tool
1919
- G304
20+
# G404: Weak RNG is fine; math/rand/v2 only drives simulation output, which is not security-sensitive
21+
- G404
2022
errcheck:
2123
# These write to stdout/files in hot paths; errors are intentionally ignored
2224
exclude-functions:

CHANGELOG.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,26 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [Unreleased]
8+
## [0.5.1] - 2026-06-03
9+
10+
### Fixed
11+
- Data race in simulation mode: migrated `internal/dns/simulate.go` to `math/rand/v2`, whose top-level functions are goroutine-safe and auto-seeded. `SimulateResolution` is now safe to call concurrently (previously a shared `*math/rand.Rand` was used from every worker).
12+
- Send-on-closed-channel race in `scan.Run`: the progress ticker goroutine now signals its own exit (`tickerStopped`) and guards its send with a select, and `Run` waits for that exit before emitting `EventDone`, so the deferred `close(events)` can no longer race an in-flight ticker send.
13+
- TUI now renders the "Aborted" status when a scan is cancelled with `ctrl+c` (the scan view is marked aborted so the subsequent `EventDone` shows partial counts).
14+
- TUI form no longer blocks a live-mode scan when the Hit Rate field is empty or out of range; hit rate is validated only when Simulate is on.
15+
- `-version` now reports the correct version (`subenum v0.5.1`).
16+
- Docker build: the builder now copies `go.sum` and runs `go mod download` before building, the base image satisfies the module Go version, and `main_test.go` is no longer copied into the build image.
17+
18+
### Changed
19+
- Go minimum version reconciled to 1.24.2 across `go.mod`, the Dockerfile base image, README, and docs (the charmbracelet TUI dependencies require it); direct vs indirect dependency classification corrected via `go mod tidy`.
20+
21+
### Added
22+
- Tests: concurrent `SimulateResolution` test, `internal/scan` runner tests (concurrent simulate run and mid-scan context cancellation), and `internal/tui` form validation tests.
23+
24+
### Docs
25+
- README facelift: plain-text description under the badges, a copy-paste quick-start block, the TUI screenshot promoted to a hero position, PRs-Welcome and platform badges, and removal of em dashes for a clean human-authored look.
26+
- ARCHITECTURE: corrected the progress ticker interval (1 second) and the argument-parsing section (`flag.*Var` into a `cliFlags` struct).
27+
- Removed the unused, duplicate `docs/assets/title.svg`.
928

1029
## [0.5.0] - 2026-03-14
1130

Dockerfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
FROM golang:1.22-alpine AS builder
1+
FROM golang:1.24.2-alpine AS builder
22

33
WORKDIR /app
44

5-
# Copy go.mod and go.sum first to leverage Docker cache
6-
COPY go.mod ./
5+
# Copy module files first and download deps to leverage Docker layer caching
6+
COPY go.mod go.sum ./
7+
RUN go mod download
78

89
# Copy source code
910
COPY main.go ./
10-
COPY main_test.go ./
1111
COPY internal/ ./internal/
1212

1313
# Build the binary with optimizations

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
[![Build](https://img.shields.io/github/actions/workflow/status/TMHSDigital/subenum/go.yml?branch=main&style=for-the-badge&label=build)](https://github.com/TMHSDigital/subenum/actions)
88
[![Release](https://img.shields.io/github/v/release/TMHSDigital/subenum?style=for-the-badge)](https://github.com/TMHSDigital/subenum/releases)
9-
[![Go](https://img.shields.io/badge/Go-1.22+-00ADD8?style=for-the-badge&logo=go&logoColor=white)](https://go.dev)
9+
[![Go](https://img.shields.io/badge/Go-1.24.2+-00ADD8?style=for-the-badge&logo=go&logoColor=white)](https://go.dev)
1010
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg?style=for-the-badge)](LICENSE)
1111
[![CodeQL](https://img.shields.io/github/actions/workflow/status/TMHSDigital/subenum/codeql.yml?label=CodeQL&style=for-the-badge)](https://github.com/TMHSDigital/subenum/actions/workflows/codeql.yml)
1212
[![Go Report Card](https://goreportcard.com/badge/github.com/TMHSDigital/subenum?style=for-the-badge&v=0.5.0)](https://goreportcard.com/report/github.com/TMHSDigital/subenum)
@@ -87,7 +87,7 @@ flowchart LR
8787

8888
## Installation
8989

90-
**Prerequisites:** Go 1.22+ &middot; Git &middot; Make _(optional)_ &middot; Docker _(optional)_
90+
**Prerequisites:** Go 1.24.2+ &middot; Git &middot; Make _(optional)_ &middot; Docker _(optional)_
9191

9292
<details>
9393
<summary><strong>Build from source</strong></summary>
@@ -272,7 +272,7 @@ No flags required. Fill in the form and press `ctrl+r` to start scanning. Last-u
272272

273273
| Layer | Components |
274274
| :--- | :--- |
275-
| Core Engine | Go 1.22 &middot; `net.Resolver` &middot; `context` &middot; `sync/atomic` |
275+
| Core Engine | Go 1.24.2 &middot; `net.Resolver` &middot; `context` &middot; `sync/atomic` |
276276
| Concurrency | goroutines &middot; channels &middot; `sync.WaitGroup` &middot; `sync.Mutex` |
277277
| TUI | Bubble Tea &middot; Bubbles (textinput, viewport, progress) &middot; Lip Gloss |
278278
| Infrastructure | Docker &middot; Alpine &middot; Make &middot; docker-compose |

docs/ARCHITECTURE.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,19 @@ internal/tui/config.go — Session persistence (load/save ~/.config/sube
4040
### 2.1. Argument Parsing
4141

4242
* **Purpose**: This component is responsible for processing the command-line arguments provided by the user when `subenum` is executed. It extracts the target domain, the path to the wordlist file, the desired number of concurrent workers, and the DNS lookup timeout.
43-
* **Implementation**: Utilizes Go's standard `flag` package.
44-
* `flag.String("w", "", "Path to the wordlist file")`: Defines the wordlist file flag.
45-
* `flag.Int("t", 100, "Number of concurrent workers")`: Defines the concurrency level flag.
46-
* `flag.Int("timeout", 1000, "DNS lookup timeout in milliseconds")`: Defines the DNS timeout flag.
47-
* `flag.String("dns-server", DefaultDNSServer, "DNS server to use")`: Defines the custom DNS server flag.
48-
* `flag.Bool("v", false, "Enable verbose output")`: Defines the verbose flag.
49-
* `flag.Bool("progress", true, "Show progress during scanning")`: Defines the progress reporting flag.
50-
* `flag.Bool("version", false, "Show version information")`: Defines the version flag.
51-
* `flag.String("o", "", "Write results to file")`: Defines the output file flag.
52-
* `flag.Int("attempts", 0, "Total DNS resolution attempts per subdomain")`: Defines the attempt count flag.
53-
* `flag.Int("retries", 0, "Deprecated: alias for -attempts")`: Deprecated retry flag.
54-
* `flag.Bool("force", false, "Continue scanning on wildcard DNS")`: Defines the force flag.
55-
* `flag.Parse()`: Parses the provided arguments.
43+
* **Implementation**: Utilizes Go's standard `flag` package. `parseFlags()` binds every flag into a `cliFlags` struct using the `flag.*Var` forms, then calls `flag.Parse()`.
44+
* `flag.StringVar(&f.wordlistFile, "w", "", ...)`: Binds the wordlist file flag.
45+
* `flag.IntVar(&f.concurrency, "t", 100, ...)`: Binds the concurrency level flag.
46+
* `flag.IntVar(&f.timeoutMs, "timeout", 1000, ...)`: Binds the DNS timeout flag.
47+
* `flag.StringVar(&f.dnsServer, "dns-server", DefaultDNSServer, ...)`: Binds the custom DNS server flag.
48+
* `flag.BoolVar(&f.verbose, "v", false, ...)`: Binds the verbose flag.
49+
* `flag.BoolVar(&f.showProgress, "progress", true, ...)`: Binds the progress reporting flag.
50+
* `flag.BoolVar(&f.showVersion, "version", false, ...)`: Binds the version flag.
51+
* `flag.StringVar(&f.outputFile, "o", "", ...)`: Binds the output file flag.
52+
* `flag.IntVar(&f.attempts, "attempts", 0, ...)`: Binds the attempt count flag.
53+
* `flag.IntVar(&f.retries, "retries", 0, ...)`: Binds the deprecated retry flag.
54+
* `flag.BoolVar(&f.force, "force", false, ...)`: Binds the force flag.
55+
* `flag.Parse()`: Parses the provided arguments into the `cliFlags` struct.
5656
* `flag.Arg(0)`: Retrieves the positional argument (the target domain).
5757
* **Interactions**: The parsed values are used to configure the subsequent components, such as the Wordlist Processing and DNS Resolution Engine. Input validation is performed to ensure valid values for critical parameters like concurrency, timeout, DNS server format (validated via `validateDNSServer`), and domain syntax (validated via `validateDomain`).
5858

@@ -105,7 +105,7 @@ internal/tui/config.go — Session persistence (load/save ~/.config/sube
105105
* **Verbose Output** (when `-v` flag is enabled):
106106
* Configuration summary, per-query DNS resolution info, and final scan statistics — all via `Info` to stderr.
107107
* **Progress Reporting** (when `-progress` flag is enabled):
108-
* A dedicated goroutine using a 2-second ticker calls `Progress` on stderr.
108+
* A dedicated goroutine using a 1-second ticker calls `Progress` on stderr.
109109
* **Interactions**: All components route output through the `Writer`. Since results are the only thing on stdout, piping (`| cut -d' ' -f2`) works without `-progress=false`.
110110

111111
### 2.6. Progress Monitoring
@@ -117,7 +117,7 @@ internal/tui/config.go — Session persistence (load/save ~/.config/sube
117117
* `processedWords`: An atomic counter that's incremented each time a subdomain is checked.
118118
* `foundSubdomains`: An atomic counter that's incremented each time a valid subdomain is found.
119119
* **Progress Display** (on stderr):
120-
* A dedicated goroutine using a ticker (running every 2 seconds) calls `Writer.Progress`
120+
* A dedicated goroutine using a ticker (running every 1 second) calls `Writer.Progress`
121121
* Uses `\r` carriage return to update the same line repeatedly
122122
* Shows percentage completion, processed count, and found count
123123
* **Interactions**: The Progress Monitoring component works alongside the worker goroutines, using atomic operations to safely track counts across multiple goroutines. Writing to stderr keeps stdout pipe-clean.

docs/CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ See the [Code of Conduct](CODE_OF_CONDUCT.html).
1313

1414
### Prerequisites
1515

16-
- Go 1.22 or later
16+
- Go 1.24.2 or later
1717
- Git
1818
- Make (optional but recommended)
1919
- Docker (optional, for containerized development)

docs/DEVELOPER_GUIDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ This guide provides information for developers looking to contribute to or build
1313

1414
To work with `subenum`, you'll need:
1515

16-
* **Go Programming Language**: [Go 1.22+](https://golang.org/dl/) is required.
16+
* **Go Programming Language**: [Go 1.24.2+](https://golang.org/dl/) is required.
1717
* **Git**: For version control.
1818
* **Text Editor or IDE**: VS Code, GoLand, or any editor with Go support is recommended.
1919

docs/assets/title.svg

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)