Changelog
All notable changes to caddy-analyzer will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.7.2 — 2026-09-05
Fixed
- Log path readability on light terminals (#100): request paths in
tailand the--watchlive log stream no longer force bright white (255), which was unreadable on white backgrounds. Paths now use the terminal default foreground in bold, so they stay legible on both light and dark themes without any flags or configuration. - Self-update cosign verification:
caddy-analyze updatefailed with--trusted-root only supported with --new-bundle-formatbecause releases published old-format bundles. Releases now publish new-format Sigstore bundles, and the updater falls back to the legacy certificate/signature sidecars whenever a bundle is not in the new format.
0.7.1 — 2026-09-01
Fixed
- Progress bar for large analyses: restore deterministic progress for finite local files, including
--detect, while retaining the animated spinner for streaming sources. The spinner now advances independently while expensive detection work is running.
Docs
- Complete command reference: document every command, subcommand, global flag, command-specific flag, safety requirement, output mode, and common workflow in English and Italian.
0.7.0 — 2026-09-01
Added
- Custom detection patterns (#76): load validated, repeatable JSON rule files with URI, header, User-Agent, and combined matching sources.
- Remote audit delivery (#70, #77): forward guard, block, and unban events to syslog or generic, Slack, Discord, and PagerDuty webhooks with bounded retries and per-IP rate limiting.
- Elasticsearch/OpenSearch and Loki exporters (#74): publish aggregated reports over authenticated HTTP with batching, retry, and bulk error handling.
- Cosign bundle verification (#93): new releases use Sigstore bundles and trusted roots while older releases remain verifiable through legacy signature sidecars.
- Guard dry-run (#78): exercise thresholds, detection, blocklists, and country rules without changing firewall rules or persistent state; emits
would_blockevents and a summary. - Persistent baselines (#73): save versioned JSON snapshots and compare future runs with
--against, configurable regression thresholds, structured output, and CI-friendly exit codes. - Bounded analysis caches (#69): replace unbounded grep/glob caches with concurrent LRU caches.
- O(1) detector LRU updates (#68): replace linear IP recency updates with a map-backed linked list.
- Single-pass progress analysis (#66): remove the full-file pre-scan that doubled I/O for large logs.
- Container deployment examples (#72): add a hardened Docker Compose demo and an opt-in, non-root Helm chart.
- Shared source fan-in (#65): centralize watch and guard stream coordination with consistent cancellation and error policies.
- Contributors section (#82): add an automatically updated contributor list to the README.
Security
- Remote notification failures never block firewall decisions, and webhook credentials are excluded from diagnostics.
0.6.6 — 2026-09-01
Added
- Automatic City GeoIP download: download the GeoLite2 City database alongside Country and ASN data unless
--no-auto-downloadis set.
0.6.5 — 2026-09-01
Fixed
- Cosign platform checksum selection: select the exact downloaded cosign asset instead of the first
cosignentry in the multi-platform checksum manifest.
0.6.4 — 2026-08-31
Fixed
update --versionrelease lookup: preserve thevprefix when querying GitHub for a pinned release tag.
Added
- Parallel analysis workers (#75):
--workers Nparallelizes log parsing while preserving input order for stateful detection and aggregation;0uses the available CPU count. - City GeoIP enrichment and heatmap (#71): local City mmdb data now populates city and coordinates, with
top city, city report sections, and an inline SVG geographic heatmap. - Modern bot detection (#67): classify GPTBot, ChatGPT-User, ClaudeBot, anthropic-ai, Bytespider, CCBot, Amazonbot, Applebot-Extended, PerplexityBot, meta-externalagent, and DataForSeoBot as bots.
0.6.3 — 2026-08-31
Fixed
- Automatic cosign download: use the current
cosign_checksums.txtasset name when downloading cosign for signature verification.
0.6.2 — 2026-08-31
Fixed
- Selective defanging (#63): IPv4 addresses are now validated before defanging, preventing version numbers and invalid dotted numeric sequences from being altered. PR #85 — @TLNing260310
--trust-forwardedignored intopandtail: forwarded client IPs are now applied before filtering and GeoIP enrichment in both subcommands. Closes #64.
Changed
- Documentation refactor (#86): rebuilt the documentation site with a templated structure, English and Italian pages, shared navigation, and updated references. PR #86 — @lenny-ts
0.6.1 — 2026-08-31
Added
- GeoIP entry filters (#37):
--country,--exclude-country,--asn,--exclude-asnfilter log entries by GeoIP data. Supports both ISO codes (IT,US) and country names (Italy,United States). — @lenny-ts - Auto-download cosign (#62):
caddy-analyze updatenow automatically downloads cosign for signature verification when not installed, removing the manual setup requirement. — @lenny-ts
Fixed
- Guard output now shows blocklist/country-block bans (#83): blocklist and country-block bans were only logged to audit but not shown in terminal output. — @lenny-ts
- Unblock idempotent:
unbanand guard expiry no longer fail with "partial unblock failures" when the iptables rule doesn't exist in one chain (hybrid mode). — @lenny-ts
0.6.0 — 2026-08-30
Added
- Firewall backend redesign: multi-backend support (iptables, Docker DOCKER-USER, nftables, hybrid) with automatic environment detection. Guard now applies rules to both INPUT and DOCKER-USER chains when Docker containers are detected, solving the issue where blocked IPs bypassed the firewall in Dockerised Caddy deployments. — @lenny-ts
- Whitelist command:
caddy-analyze whitelist --add/--remove/--list/--initmanages the never-block list. Auto-loaded by guard via/etc/caddy-analyzer/whitelist.txt. — @lenny-ts - Operational tuning flags (#56):
--geo-cache-ttl,--geo-cache-size,--iptables-timeoutreplace compile-time constants. — @dchaudhari7177
Fixed
loadStatedoes not recreate iptables rules (#79): on guard restart,loadState()restores IPs to the in-memory map but did not callblocker.Block()to recreate iptables rules. Banned IPs could pass through until the sliding window filled again. — @lenny-ts- Graceful shutdown: guard now flushes state and suppresses noisy "context canceled" errors on Ctrl+C. — @lenny-ts
- Active filters not shown in report header (#51):
--max-latency,--min-size,--max-size,--level,--ops-onlywere omitted from the "Filters:" line. — @dchaudhari7177 validateIP/validateIPOrCIDRduplication (#49): unified into a singlevalidateIP. — @dchaudhari7177
Changed
- Sigma rule UUIDs are now RFC 4122 version 5 (#59): MD5-based identifiers were not valid UUIDs. Now uses
uuidV5with a derived namespace, matching Sigma conventions. Rules exported before this release carry different UUIDs. — @dchaudhari7177 - GitHub Actions SHA-pinned (#55): all third-party actions pinned to full commit SHAs. — @dchaudhari7177
0.5.1 — 2026-08-29
Fixed
- Docker log monitoring (
docker://) not capturing entries (#57):execLinesonly read the child process's stdout viaStdoutPipe, but Caddy v2 (and other tools) write access logs to stderr by default.docker logspreserves this stream separation, so all log data went to stderr and was silently dropped. ReplacedStdoutPipewithio.Pipe()and set bothcmd.Stdoutandcmd.Stderrto the pipe writer, merging the two streams. A separate goroutine callscmd.Wait()then closes the pipe to avoid a deadlock where the scanner blocks onio.PipeReader.Readwhile the writer is still open.docker://containersources now work regardless of whether the target writes to stdout, stderr, or both.
Changed
- Deduplicate
yamlEscape/yamlQuote: removedyamlQuoteincmd/export_sigma.go, an exact copy ofyamlEscape; its four call sites now callyamlEscape. #48 — @dchaudhari7177
Fixed (also in 0.5.1)
- Zero-duration delta formatting:
formatDurationDelta(0)now uses the sharedoutput.FormatDurationformatter instead of a hardcoded"0ms", returning"N/A"consistently. #47 — @Labeeb2339
Added
- GeoIP entry filters (
--country/--exclude-country/--asn/--exclude-asn) (#21): keep or drop log entries by GeoIP country code (ISO 3166-1, case-insensitive) and autonomous system number, incaddy-analyze,tail,top, anddiff. Same semantics as--ip/--exclude-ip: allowlist/denylist per dimension (mutually exclusive within a dimension, AND-combined across dimensions), unresolved entries (private IPs, mmdb misses) are dropped by allowlists and kept by denylists. Requires a GeoIP mmdb — validated up front with a clear error when an explicit--geoip-dbis missing or auto-download is disabled without any discoverable database. Filters surface in the report header ("Filters:" line), JSON/CSV metadata, HTML reports, and trigger color-coded listing mode like other entry filters.
Fixed
- Enrich-before-filter order: in one-shot mode and
tail, entries are now GeoIP-enriched before filtering when geo-based filters are active, so--country/--asnsee resolved data (top,diff, follow, and interval already enriched before the engine matched). Non-geo runs keep the filter-first optimization: rejected rows are still never looked up. #21
0.5.0 — 2026-08-22
Added
updatesubcommand for self-update with cosign verification (#16):caddy-analyze updatedownloads the latest GitHub release, verifies it, and atomically replaces the running binary. Verification is fail closed: cosign keyless signature check onchecksums.txt(certificate identity anchored to this repo's release workflow) plus a SHA256 match against the signed manifest; a missingcosignbinary or any verification failure aborts with nothing installed — no unverified fallback. Flags:--check(report only),--version <tag>(pin an exact release),--force(reinstall/allow downgrade),--install-dir <dir>(target another directory when the binary is root-owned). Handles GitHub API rate limits (cached last-check fallback for--check, actionable error otherwise), refuses downgrades without--force, preserves file permissions, and uses the Windows rename-aside trick for running.exefiles.- Operational (non-HTTP) log support: Caddy operational events — config loads, TLS certificate operations, upstream dial errors, admin shutdowns — are now parsed, filtered, and aggregated alongside HTTP access entries. Non-
"handled request"JSON lines no longer get silently dropped: they populate a new "Operational Events" report section (total events, error count, level breakdown, top loggers, top messages) in every output format (table,json,csv,html). Unknown JSON fields are preserved in anExtramap and shown inline intailoutput (e.g.upstream=10.0.0.5:8080). New flags:--level error,warn,info,debugfilters operational events by level (repeatable/comma-separated),--ops-onlyhides HTTP entries entirely. - Operational tab in
--watchdashboard: new 8th tab (key8) showing live operational event counts by level, logger, and message. - Sample log fixtures:
testdata/sample.log(68 curated lines, one per detection category plus benign baseline) andtestdata/large.log(~50,000 lines, ~27 MB, ~95% benign / ~5% malicious cycling all 26 categories over 24h) — let users exercise every command, including the full detection engine, without a live Caddy server. All client IPs use TEST-NET ranges (RFC 5737), so nothing in the fixtures points at a real host. testdata/generate.py: stdlib-only Python generator producing both fixtures. Supports--sampleand--largeflags. Deterministic output (seeded RNG, fixed epoch anchor matchingparser_test.go); the script is the source of truth — re-run it instead of hand-editing the.logfiles.
Docs
- README: new "Sample Logs & Test Fixtures" section covering usage (
caddy-analyze --detect testdata/sample.log,tail -d, JSON output, HTML report,diff, large.log performance demo) and regeneration (python3 testdata/generate.py). - docs/sources.html: new "7. Sample Logs & Test Fixtures" section mirroring the README, with a fixtures table and the regeneration callout.
0.4.1 — 2026-08-18
Fixed
- Apparent freeze with no log source (#19): when no source is specified, no config file exists, and stdin is a TTY,
caddy-analyzerno longer falls back to a blocking stdin read that hangs forever with no output. It now prints a clear error listing the supported source formats.StdinReader.Readalso rejects a TTY directly (defense-in-depth) and prints a "reading log lines from stdin..." hint in the pipe case.--watchrefuses a stdin source up front instead of starting a dashboard that races bubbletea for fd 0. #19 --watchstartup blocked on GeoIP download:newGeoIPEnricher()ranautoDownloadGeoIPsynchronously (5-min per-file timeout), so the dashboard did not appear until the download finished.--watchnow usesNewGeoIPAsync, which returns a lazy enricher that downloads in the background; lookups return a zeroGeoInfountil the database is swapped in, and the Geo tab shows a "downloading in background..." hint. #19- Usage spam on source errors:
SilenceUsage: trueadded to the root,tail,top, andguardcommands so a missing source prints only the error (not the full help text). #19 - GeoIP search paths on Windows: resolve home directory with
os.UserHomeDir()instead ofos.Getenv("HOME")(typically unset on Windows), so GeoIP/ASN databases are discovered underC:\Users\<user>\.config\caddy-analyzer\rather than/.config/.... PR by @MsfPablo. #27 - Follow/interval mode filters: entry filters (method, status, --only-5xx, IP, grep, forwarded-IP) are now applied before GeoIP enrichment. Previously discarded rows were still enriched, wasting lookups and showing filtered-out entries in the live report. PR by @myukitty. #26
Changed
- TUI tab navigation: simplified cycling through views with modulo arithmetic (no more boundary checks). PR by @intactov. #18
0.4.0 — 2026-08-17
Added
- Blocklist feed system:
blocklistsubcommand with four actions —refresh(download + cache all feeds),list(per-feed status),config(print resolved sources),init(persist flag settings tocaddy-analyzer.json). Feeds are cached as a CIDR trie in~/.cache/caddy-analyzer/blocklists/(7-day TTL). Flags:--cache-dir,--no-default-blocklists,--blocklist-config,--blocklist-remove. - 8 default blocklist feeds: Spamhaus DROP v4/v6, FireHOL level 1/2, CINS Army, Tor exit nodes, Emerging Threats, AbuseIPDB s100-7d mirror. JSON Lines (Spamhaus) and plain-text formats supported.
- Guard blocklist integration: incoming IPs are checked against the CIDR trie for immediate block.
--no-blocklistdisables;--blocklist-refresh(default6h) controls background re-fetch. - Guard country-block:
--country-block CN,RU,IRimmediately blocks IPs by GeoIP country code. Fails fast if no mmdb is available. - GeoIP enrichment: offline mmdb lookup (no API key, no network at query time).
--geoip-dbwith auto-discovery in cwd,~/.config/caddy-analyzer/,/var/lib/caddy-analyzer/,/usr/share/GeoIP/. Auto-downloadsGeoLite2-Country.mmdb+GeoLite2-ASN.mmdbfrom the P3TERX mirror on first run; disable with--no-auto-download. top country/top asndimensions with human-readable country names ("Italy" instead ofIT). Country and ASN sections now in the default report (auto-hidden when no GeoIP data).--watch(live dashboard) GeoIP tab: new "Geo" view (key7) showing top client countries (human-readable names) and top ASN. Log entries are enriched inline as they stream in; the tab degrades to a disabled hint when no mmdb is available.- Documentation site: glassmorphism-design docs (index, subcommands, security, sources, installation) with TOC sidebar, back-to-top, Lighthouse-optimized performance.
Fixed
- GeoIP download URLs: dead
download.dbip.com(DNS does not resolve) replaced with the P3TERX/GeoLite.mmdb GitHub release mirror. Auto-download now fetches both country and ASN databases. - CINS Army URL corrected to
http://cinsscore.com/list/ci-badguys.txt. - Country codes shown instead of names in
top countryand the default report.
Changed
- AbuseIPDB enricher removed: the
pkg/enrich/abuseipdb.gofile (shipped in 0.3.0 but never wired to any command) is deleted. GeoIP mmdb is the sole enrichment backend. - Guard startup summary now prints blocklist stats and country-block list alongside existing thresholds.
- Go 1.25.13 (was 1.24.6).
0.3.0 — 2026-08-06
Added
- 3 new detection categories (26 total): JWT abuse (
jwt_abuse), object enumeration/BOLA (object_enumeration), beaconing/C2 (beaconing). All tagged with MITRE ATT&CK technique IDs. export-sigmasubcommand: exports 23 detection categories as Sigma YAML for SIEM import. Includes MITRE ATT&CK tags and deterministic UUIDs.--defangflag: defangs IPs (.→[.]) and URL schemes (http://→hxxp://) across all commands for safe IOC sharing.tail --detect: inline threat highlighting on streamed entries. IP colored by severity, attack types appended after a→arrow. Clean entries unchanged.- Progress bar: determinate bar on TTY for file analysis (
caddy-analyze,top,diff); indeterminate spinner for non-file sources. Auto-disabled on pipe. - Threat-intel enrichment: GeoIP enrichment via DB-IP/MaxMind mmdb (offline, zero API key).
--geoip-dbflag with auto-discovery. Country/ASN top-N dimensions (--top country,--top asn). - Guard features: sliding-window rate limiting, distributed-scan defense (
--subnet-limit), RPS anomaly alerting (--rps-anomaly), credential stuffing detection (--cred-stuffing-limit),--trust-forwardedfor reverse proxy/CDN. --state-fileonblock/unban: manual blocks/unbans sync with guard state file — survive restarts.- Detection engine 2x throughput: case-fold elimination, per-source marker triage, literal fast path. ~7K lines/sec with
--detect(was ~3.5K). - Streaming latency histogram: O(1) log10-spaced buckets replace O(n) slice. Saves ~80MB on million-line logs.
- MITRE ATT&CK tags on all detections. Structured detections in JSON output.
- New filter flags:
--host,--max-latency,--min-size/--max-size,--max-cardinality,--ua-rotation. - Subcommand flag inheritance: shared flags (
-t,-f,-o, filters) now persistent acrosstop,diff,tail,config. - Dedicated iptables chain (
CADDY_ANALYZER) with comment marker —unbanonly touches rules created by this tool. - Cosign signature verification in
install.sh. Dockerfile non-root user. CI coverage gate (≥50%).
Fixed
- Guard: shutdown race losing state on Ctrl+C (now waits for
saveState); dirty-flag race losing concurrent blocks;ListBlockedIPsmisleading error on fresh systems; manualblock/unbannot synced to state; duplicate iptables rules on double-block;block/unbanalways exit 0;loadStatehitting real iptables in tests. - Detection engine: zero timestamp corrupting
StartTime; unboundedPathTimestampsper IP (now capped at 1K); FIFO eviction mislabeled as LRU (now true LRU);extractPureLiteralsdropping 1-char alternatives;lowercaseFoldmissingOpCharClass; UA-rotation firing only once;MinDurationcorrupted by zero/negative durations. - Audit logger: double-
Close()panic; goroutine leak after rotation failure; no reopen after write error. - Reader: follow mode + multiple files only reading first file (now concurrent fan-in).
- TUI:
truncate(s, 0)panic; negative table height on tiny terminals;StreamEndMsgfreeze. - Output: ANSI codes leaking to
-ofiles;-ocreating files with 0666 (now 0600 with dir creation). - Parser: silent error on Status/Size parse;
classifyUserAgentrebuilding map every call + non-deterministic BotName. - cmd: SIGPIPE in
tail | head; signal goroutine leaks inroot/tail/guard;--top 0ignored intopcommand. - 30+ earlier fixes: JWT base64 decode, beaconing per-path, defang in follow/interval modes, authFailPaths map leak, ring buffer off-by-one, sigma YAML escaping, enrichment cap, parseInt overflow, math.Sqrt on zero, duration histogram P99, guard busy-loop, partial lines at EOF, journalctl output format, and more (see git log for full detail).
Changed
- Go 1.24.6 (23 stdlib vulnerabilities fixed).
- golangci-lint v2 config format. gosec excludes G401/G501 (MD5 for deterministic UUIDs). gitleaks
.gitleaksignorefor test fixtures. - IP eviction: true LRU (was FIFO). Enrich cache bounded to 10K entries. File output 0600 with parent dir 0750.
- Scanner detection:
curl,wget,python-requestsno longer flagged as scanners standalone (too many false positives). - Narrowed false-positive patterns: SSRF metadata,
.envpath delimiters, SSTI regex escaping, XSS token cleanup.
0.2.0 — 2026-08-01
Added
- Multi-category detection:
DetectAll()returns all matching attack categories per request instead of stopping at the first match. Polyglot payloads (e.g. SQLi+XSS) are now classified as both. - Confidence scoring: Every detection pattern carries a 1-10 score based on specificity. Included in JSON output for filtering and prioritization.
- Guard audit logging: Structured JSON-lines audit log (timestamp, action, IP, reason, duration, user) via
--audit-logonguard,block, andunban. File created with0600permissions. - Guard state persistence:
--state-file(default/var/lib/caddy-analyzer/blocked.json) survives restarts; expired entries cleaned on load. - Guard IP allowlist:
--never-block(comma-separated IPs/CIDRs) and--never-block-file(file, one per line,#comments) prevent banning trusted IPs. Flags are merged. - IP validation:
validateIP()accepts IPv4/IPv6/CIDR and rejects flag injection. Applied to all three iptables call sites. - Version injection via ldflags:
Versionvariable populated by GoReleaser, CI, and Dockerfile. - CI quality gates:
go vet,golangci-lint,govulncheck, coverage reporting. Actions SHA-pinned,permissions: contents: read. Secret scanning (gitleaks) and SAST (gosec, with G104/G204/G304 excluded as inherent to CLI design). - SBOM and release signing: SPDX JSON SBOMs via Syft, cosign keyless signature uploaded as release asset.
- CODEOWNERS: Requires review on CI workflows, installers, and build config.
Fixed
- Regex false positives: Removed 11 duplicate patterns, bounded 8 unbounded
.*quantifiers, removed overly broad/docs/admin probe. - Race condition on
blockedmap:sync.Mutexprotection, fixed bypass where blocked IPs weren't removed afteriptables -D, and false-positive marking oniptables -Afailure. parseBlockedIPsfield index bug: Read wrong column, returning garbage IPs.- Swallowed
ParseDurationerrors:--duration abcand--interval abcnow fail instead of silently using 0 (permanent block). - Goroutine leak and DoS:
unblockAfternow usesselectwithctx.Done()(cancelled on Ctrl+C). Replaced per-IPtime.Sleepgoroutines with a single min-heap-based expiry loop. - File rotation data loss:
readFileAndFollowdetects rotation viaos.SameFile()and reopens. cmd.Wait()errors ignored: Now logged; zombie processes reaped afterProcess.Kill().install.sh: Addedset -euo pipefailand checksum verification.- Custom HTML escaper: Replaced with
html.EscapeString(also escapes'). - Scanner UA list duplicates: Removed 5 duplicate entries.
- Windows CI test failures: File-permission tests now skip on Windows (Unix perms not honored).
cmd.Wait()error explicitly discarded afterProcess.Kill().
Changed
- Detection gap coverage: 4 new pattern families (SSTI FreeMarker/ERB/Thymeleaf, Java/Node deserialization, CRLF Java ghost bits, open redirect backslash bypass).
- Go 1.24 aligned across
go.mod, Dockerfile, CI matrix, and release workflow. - Dockerfile production image pinned to
alpine:3.20with SHA256 digest. listBlockedIPsswitched toiptables -S: Stable one-rule-per-line format instead of locale-dependentiptables -L.- Config file permissions tightened: Directory
0755→0750, file0644→0600(gosec G301/G306).
0.1.3 — 2026-07-30
Added
- Expanded to 22 attack categories (was 15): added XXE/XInclude, Open Redirect, LDAP Injection, XPath Injection, CRLF Injection, Prototype Pollution, SSI Injection, SSRF (cloud metadata / protocol smuggling), SSTI (Freemarker, Jinja2, MRO), NoSQL Injection (
$ne,$gt,$regex,$where), GraphQL Introspection (__schema,__type), LFI Wrapper Abuse (phar://,data://,compress.*), WordPress probes, and CGI probes. - Raw URI matching: Percent-encoded path traversal sequences (
%c0%ae%c0%ae%c0%af,%252e%252e%252f) and internal host probes are checked against the raw URI before URL unescaping — closing evasion gaps. - Expanded existing signatures: RCE now matches time-based exfiltration (
sleep,ping,/dev/tcp/); Log4j catches obfuscated variants (${lower:jndi,${${::-j}}); path traversal catches null-byte tricks (%00..); sensitive file probes cover.gitignore,composer.json,package.json; admin probes cover/h2-console,/heapdump,/jolokia; scanner UA list includeshttpx,nuclei,ffuf,katana,dalfox,xsstrike,commix,tplmap,nosqlmap. - Comprehensive test suite: 55+ test cases covering all 22 categories, dual-pass matching, and false positives.
- Security-first README: Hero callout, Demo GIF at top, 22-row detection table with examples, restructured for immediate security impact.
- docs/security.html: Updated with all 22 categories and compact pattern table.
Changed
- Detection engine: Introduced
rawPatternspre-compiled init block for rules that must match against the raw (non-unescaped) URI, executed before the mainpatternsblock. - README reordered: Hero security callout → Demo GIF → Security Detection → Quick Start → Why caddy-analyzer? → Features → Installation → Docs.
- Help text:
cmd/root.goandcmd/guard.gonow reference 22 categories and dual-pass engine.
0.1.2 — 2026-07-29
Added
- Per-IP & CIDR Filtering:
--ipnow accepts both single IPs (1.2.3.4) and CIDR subnets (10.0.0.0/8).--exclude-ipalso supports CIDR. - Smart Filter Listing: When entry-level filters are active (
--ip,--5xx,--no-bots, etc.),caddy-analyzenow shows a color-coded log listing (liketail) instead of the aggregate report — making filtered output immediately actionable. - Filter Support for
tail: Thetailsubcommand now accepts all root-level filters (--ip,--5xx,--no-bots, etc.) for real-time filtered streaming. - Active Filter Display: All active filters are shown in the report header for table, JSON, CSV, and HTML formats.
- TUI Dashboard Colors: The real-time stream tab (tab 2) in
--watchmode now uses the same color scheme ascaddy-analyze tail(2xx green, 3xx cyan, 4xx yellow, 5xx red, IP purple, etc.). - Suspicious Request Details in
--detect: The security report now shows the actual suspicious requests (detection type, description, method, path) per offending IP in all output formats. - Public
MatchEntryAPI: Exportedanalysis.MatchEntry()to allow external use of filter logic.
Fixed
--ipfilter not working: The--ipflag was declared and parsed but the filtering logic was missing inEngine.match(). Now correctly filters by IP/CIDR.
Changed
- Help text: Updated root command help with filter examples and expanded flag descriptions.
0.1.1 — 2026-07-28
Added & Improved
- Focused Security Inspection Mode (
--detect): Running--detectnow outputs a standalone, zero-noise Security Threat Inspection Report focused purely on attack alerts, offending IPs, and threat categories. - Enhanced
topCommand Usability: Automatically defaults topathdimension when log source is passed directly (caddy-analyze top access.log). Added-b, --byflag. - Enhanced
configCommand Usability: Addedshowandresetactions with clear user feedback for managing persistent default log sources. - Clean Unix Terminal Formatting: Removed emojis from terminal outputs, adopting a crisp, high-contrast Unix developer aesthetic.
- Documentation Suite: Added complete multi-page documentation website (
docs/) with comprehensive reference tables for all 19 CLI flags and options. - Permission Diagnostics: Added friendly diagnostic hints when opening log files fails due to permission errors (
permission denied), suggestingsudoor user group membership.
Fixed
- Windows PowerShell Installer: Fixed asset filename pattern and encoding compatibility for PowerShell 5.1 in
install.ps1. - POSIX Shell Installer: Fixed release asset URL template and ASCII formatting in
install.sh.
0.1.0 — 2026-07-28
Initial Release
Core Features
- Native Caddy v2 JSON Parsing: Zero-config parsing of Caddy's structured log schema including nested TLS versions, request headers, float durations, and status codes.
- Traffic Classification: Automatic detection of human users vs search engine crawlers (Googlebot, Bingbot, Yandex, DuckDuckBot) and scrapers.
- Percentile Latency Analysis: Computes P50, P95, P99 latencies alongside average, min, and max durations.
- Bandwidth Metrics: Track bytes transferred per path and remote IP address.
Security & Anomaly Detection Engine
- Threat Detection (
--detect): Scans URIs and headers for SQL Injection, XSS, Path Traversal / LFI, Log4j / JNDI, RCE, sensitive file probes (.env,.git/config,wp-config.php,id_rsa), admin probes, and automated scanner User-Agents. - Real-time Firewall Guard (
guard): Automatically monitors log streams and blocks offending malicious IPs in real time viaiptablesrules. - Manual Ban Tools: Added
block <ip>andunban <ip>commands.
CLI & Output Formats
- Visual Terminal Bar Charts: Displays Unicode proportion bars (
████████░░) and status code badges directly in terminal output. - Real-time Streaming (
tail): Colorized real-time log viewer for streaming logs from files, Docker, K8s, or stdin. - Metric Inspector (
top): Quick top-N metric inspector by dimension (path,ip,ua,status,bandwidth). - Comparative Log Diff (
diff): Compare two log files side-by-side (baseline vs target) to detect 5xx error spikes, RPS shifts, and latency regressions. - Standalone Offline HTML Report (
-f html): Single-file dark-mode HTML report generator. - 6-Tab Interactive TUI (
--watch): Live Bubbletea terminal user interface featuring Summary, Realtime Stream, Security Alerts, Top IPs, Top Paths, and User Agents.
Multi-Source Reader
- Supports reading from local files, stdin pipe (
-), Docker containers (docker://container), Kubernetes pods (k8s://pod), and systemd journalctl (journalctl://unit).
Cross-Platform Installers & Automation
- 1-Line installer scripts for Linux/macOS (
install.sh) and Windows PowerShell (install.ps1). - GitHub Actions CI matrix testing on Ubuntu, macOS, and Windows.
- GoReleaser automated static binary build matrix for
linux/amd64,linux/arm64,linux/armv7,darwin/amd64,darwin/arm64,windows/amd64,windows/arm64. - GitHub Pages documentation site with live interactive HTML report demo.