Use UUIDv5 instead of MD5 for Sigma rule UUIDs - #59
Merged
Conversation
lenny-ts
reviewed
Aug 29, 2026
lenny-ts
previously requested changes
Aug 29, 2026
lenny-ts
left a comment
Owner
There was a problem hiding this comment.
Since PRs #49–#59 are all being merged together, please update the [Unreleased] section in CHANGELOG.md with the cumulative changes. Here's ready-to-paste content matching the project's changelog format:
## [Unreleased]
### Added
- **Operational tuning flags (#56)**: `--geo-cache-ttl` (default 24h), `--geo-cache-size` (default 50000), and `--iptables-timeout` (default 10s) replace compile-time constants, allowing runtime tuning without recompilation. Values can also be set in `caddy-analyzer.json` under the `tuning` key; CLI flags take precedence. — @dchaudhari7177
### Fixed
- **Active filters not shown in report header (#51)**: `--max-latency`, `--min-size`, `--max-size`, `--level`, and `--ops-only` were parsed but silently omitted from the "Filters:" line in report output. — @dchaudhari7177
- **`validateIP` / `validateIPOrCIDR` duplication (#49)**: unified into a single `validateIP` that accepts both bare IPs and CIDRs. — @dchaudhari7177
### Changed
- **Sigma rule UUIDs are now RFC 4122 version 5 (#59)**: `sigmaUUID` derived its identifier from MD5 and formatted the digest as `8-4-4-4-12`, which looks like a UUID but is not one — the version and variant bits were whatever the hash produced, so a consumer validating the `id` field would reject the rule. Identifiers are now `uuidV5(sigmaNamespace, "caddy-analyzer:sigma:" + title)`, matching Sigma's own convention. The namespace is derived once as `uuidV5(DNS, "caddy-analyzer")` and hardcoded as a constant, so identifiers stay stable across runs and releases. **Rules exported before this release carry different UUIDs**; regenerate them once. Implemented against `crypto/sha1` rather than adding a module dependency, and checked against RFC 4122's published test vector. — @dchaudhari7177
- **GitHub Actions SHA-pinned (#55)**: all third-party actions (`actions/checkout`, `actions/configure-pages`, `actions/upload-pages-artifact`, `actions/deploy-pages`, `goreleaser/goreleaser-action`, `softprops/action-gh-release`) pinned to full commit SHAs with version comments for supply-chain hardening. — @dchaudhari7177
- **`emitReport` extracted in `runFollowMode` (#53)**: reduced code duplication in the follow-mode interval logic. — @dchaudhari7177
- **`top` dimension help text updated (#54)**: `country` and `asn` added to the documented dimension list. — @dchaudhari7177
- **`tail --detect` example added to root help (#58)**. — @dchaudhari7177
### Docs
- **`parseTime` tests (#50)**: coverage for RFC3339, relative durations, empty input guard. — @dchaudhari7177
- **`formatDurationDelta` zero-case documented (#52)**: comment and tests explaining why `0` returns `"0ms"` instead of `"N/A"`. — @dchaudhari7177
- **Subcommands docs updated (#56)**: new tuning flags documented in the CLI reference table. — @dchaudhari7177
Owner
|
The Flags Reference table in Please add them: GeoIP flagsAfter the | --geo-cache-ttl | | 24h | How long a resolved GeoIP lookup stays cached. 0 disables caching (much slower on busy traffic). Overrides tuning.geo_cache_ttl in config |
| --geo-cache-size | | 50000 | Max cached GeoIP lookups. 0 disables caching. Raise on high-traffic servers; lower on low-memory boxes. Overrides tuning.geo_cache_size in config |Guard flagsAfter the | --iptables-timeout | | 10s | Timeout for each iptables invocation (guard). Raise for huge rulesets on busy boxes. Overrides tuning.iptables_timeout in config | |
Owner
|
Hi @dchaudhari7177, I went ahead and pushed the review fixes directly since I want to include this PR in the next release. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #23
The old output was not a UUID
Worth stating, because it is a stronger reason than MD5 being deprecated. The MD5 path formatted a 16-byte digest as
8-4-4-4-12— the right shape, but the version and variant bits were whatever the hash happened to produce. For one real rule title:Version 6 with variant 3 is not a valid UUID under any RFC, so a Sigma consumer validating the
idfield would reject the rule. That is now fixed alongside the MD5 concern.Namespace
Derived exactly as the issue specifies —
uuidV5(uuid.NameSpaceDNS, "caddy-analyzer")— then hardcoded, since it must never change.TestSigmaNamespaceIsDerivedFromTheProjectNamerecomputes the derivation and asserts it equals the constant, so the provenance is documented and checked rather than left in a comment.No new dependency
github.com/google/uuidis not ingo.mod, and the issue offered vendoring as the fallback. I implemented RFC 4122 §4.3 against stdlibcrypto/sha1instead — twelve lines:Adding a module for that seemed the wrong trade in a project with six direct dependencies. The obvious risk is a hand-rolled UUID being subtly wrong, so it is checked against RFC 4122's own published test vector:
uuidV5(NameSpaceDNS, "python.org")must equal886313e1-3b8a-5372-9b90-0c9aee199e5d. It does.SHA-1 here is a naming scheme rather than a security property — version 5 specifies it — and there is a comment saying so, so this does not read as swapping one broken hash for another.
Compatibility
Rules exported before this change carry different UUIDs. Unavoidable: the identifier is derived from the algorithm. Anyone with published rules regenerates once, and identifiers are stable from here on. Called out in the CHANGELOG under
Unreleased.Tests
cmd/export_sigma_uuid_test.go, eight cases: the RFC vector, the namespace derivation, the namespace parsing, a regex asserting version-5 and RFC-4122-variant nibbles across four titles (including an empty one and a non-ASCII one), determinism across calls, distinctness across titles, andparseUUIDaccepting the canonical form while rejecting five malformed inputs.Verification
go build ./...,go vet ./...clean;go test ./...passes in every package.crypto/md5is no longer imported anywhere undercmd/.gofmt -llists this file, but it lists untouched files such ascmd/root.gotoo — my checkout is CRLF.gofmt -don an LF-normalised copy produces no diff.