Skip to content

feat: community detection rule library — 9 curated rules embedded in binary#13

Merged
Crank-Git merged 1 commit into
mainfrom
feat/p2-community-rules
Apr 11, 2026
Merged

feat: community detection rule library — 9 curated rules embedded in binary#13
Crank-Git merged 1 commit into
mainfrom
feat/p2-community-rules

Conversation

@Crank-Git
Copy link
Copy Markdown
Owner

Summary

  • 9 curated rules embedded in the binary via go:embed, organized into 3 files:
    • recon.tomlport_scan_detector, host_sweep_detector, connection_flood
    • c2_malware.tomltls_fingerprint_flood, rapid_beaconing, slow_beaconing
    • lateral_movement.tomlinternal_host_spread, ssh_connection_burst, dst_port_spread
  • config.LoadCommunityRules() — loads and validates all embedded TOML files at startup
  • config.MergeRules(community, custom) — user rules shadow community rules of the same name, enabling per-rule disable/override without editing the binary
  • initPipeline + SIGHUP handler updated to load community rules and merge before passing to evaluator; community rules stay static across SIGHUP (only custom rules reload)

Override model

To disable a community rule, add an entry with the same name to custom_rules.toml:

[[rule]]
name    = "slow_beaconing"
enabled = false
# ... remaining required fields ...

User rules shadow community rules of the same name — no binary changes needed.

Test plan

  • TestLoadCommunityRules_Valid — all embedded files parse + validate, at least one rule returned
  • TestLoadCommunityRules_NoDuplicateNames — no name collisions across rule files
  • TestMergeRules_UserShadowsCommunity — user rule takes priority when names collide
  • TestMergeRules_EmptyCustom — community-only scenario
  • TestMergeRules_EmptyCommunity — custom-only scenario
  • TestMergeRules_OrderPreserved — community rules appear before custom rules
  • All 11 packages green

🤖 Generated with Claude Code

…binary

Ships three rule files in internal/config/rules.d/ (embedded via go:embed):

  recon.toml         — port_scan_detector, host_sweep_detector, connection_flood
  c2_malware.toml    — tls_fingerprint_flood, rapid_beaconing, slow_beaconing
  lateral_movement.toml — internal_host_spread, ssh_connection_burst, dst_port_spread

All rules use sliding windows where appropriate to catch bursts straddling
tumbling boundaries. Rules ship ready-to-use; operators tune thresholds or
disable rules by adding a same-named entry to custom_rules.toml (user rules
shadow community rules of the same name via MergeRules).

Community rules are static (embedded in binary, not reloaded on SIGHUP).
Custom rules via custom_rules.toml continue to hot-reload on SIGHUP.

Tests: LoadCommunityRules_Valid, NoDuplicateNames, MergeRules_* (5 cases).
All 11 packages green.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Crank-Git Crank-Git merged commit 93a0867 into main Apr 11, 2026
2 checks passed
Crank-Git added a commit that referenced this pull request Apr 14, 2026
…scription fix

Addresses findings from post-merge eng review of PR #13:

- Add new_ja4_burst and dga_cert_diversity rules to c2_malware.toml.
  These two rules use JA4-specific fields (ja4, ja4x) that a NetFlow sensor
  cannot see — the actual differentiator vs. volumetric-only detection.
  Both include a note that they only fire on completed TLS handshakes.

- Fix ssh_connection_burst description: was "opened more than 20 SSH
  connections" but the rule uses count_distinct(dst_ip), which measures
  distinct destination hosts, not total connection count. Corrected to
  "connected to more than 20 distinct hosts via SSH".

- Add TestMergeRules_BothNil: guards against panic if both community and
  custom rule sets are nil (edge case, not reachable in normal operation).

- Add TestCommunityRules_FireThroughEvaluator (integration test): end-to-end
  verification that LoadCommunityRules → NewCustomRules → Evaluate fires an
  alert. Specifically triggers port_scan_detector with 21 distinct dst_ports.
  Guards against silent regression if the wiring in initPipeline breaks.

- Add logShadowedRules helper in main.go: logs a warning when a user custom
  rule shadows a community rule of the same name. Called at startup and on
  SIGHUP. Previously silent; helps operators debug unexpected detection gaps.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Crank-Git added a commit that referenced this pull request May 9, 2026
feat: community detection rule library — 9 curated rules embedded in binary
Crank-Git added a commit that referenced this pull request May 9, 2026
…scription fix

Addresses findings from post-merge eng review of PR #13:

- Add new_ja4_burst and dga_cert_diversity rules to c2_malware.toml.
  These two rules use JA4-specific fields (ja4, ja4x) that a NetFlow sensor
  cannot see — the actual differentiator vs. volumetric-only detection.
  Both include a note that they only fire on completed TLS handshakes.

- Fix ssh_connection_burst description: was "opened more than 20 SSH
  connections" but the rule uses count_distinct(dst_ip), which measures
  distinct destination hosts, not total connection count. Corrected to
  "connected to more than 20 distinct hosts via SSH".

- Add TestMergeRules_BothNil: guards against panic if both community and
  custom rule sets are nil (edge case, not reachable in normal operation).

- Add TestCommunityRules_FireThroughEvaluator (integration test): end-to-end
  verification that LoadCommunityRules → NewCustomRules → Evaluate fires an
  alert. Specifically triggers port_scan_detector with 21 distinct dst_ports.
  Guards against silent regression if the wiring in initPipeline breaks.

- Add logShadowedRules helper in main.go: logs a warning when a user custom
  rule shadows a community rule of the same name. Called at startup and on
  SIGHUP. Previously silent; helps operators debug unexpected detection gaps.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Crank-Git added a commit that referenced this pull request May 9, 2026
…scription fix

Addresses findings from post-merge eng review of PR #13:

- Add new_ja4_burst and dga_cert_diversity rules to c2_malware.toml.
  These two rules use JA4-specific fields (ja4, ja4x) that a NetFlow sensor
  cannot see — the actual differentiator vs. volumetric-only detection.
  Both include a note that they only fire on completed TLS handshakes.

- Fix ssh_connection_burst description: was "opened more than 20 SSH
  connections" but the rule uses count_distinct(dst_ip), which measures
  distinct destination hosts, not total connection count. Corrected to
  "connected to more than 20 distinct hosts via SSH".

- Add TestMergeRules_BothNil: guards against panic if both community and
  custom rule sets are nil (edge case, not reachable in normal operation).

- Add TestCommunityRules_FireThroughEvaluator (integration test): end-to-end
  verification that LoadCommunityRules → NewCustomRules → Evaluate fires an
  alert. Specifically triggers port_scan_detector with 21 distinct dst_ports.
  Guards against silent regression if the wiring in initPipeline breaks.

- Add logShadowedRules helper in main.go: logs a warning when a user custom
  rule shadows a community rule of the same name. Called at startup and on
  SIGHUP. Previously silent; helps operators debug unexpected detection gaps.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant