Repository navigation
Conversation
… check that lets one rule repeat (#342) A reviewed, versioned noise catalogue keyed by vendor and detection rule id (Wazuh raw.rule.id with the normalizer's rule name, never text) lifts only the unmapped never-close class. The campaign check now needs every related alert to be the same rule repeating as benign noise over a complete related set; a different rule, a threat or unjudged alert, a never-close class, a plan awaiting approval, a truncated or blind-audit-hidden set or an old digest blocks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JmdYVXkgpNHoygVJCrUeZc
|
Review of #345 (FIX-2). I read noise_families.py, closure.py and correlation/base.py; I did not run the tests. Overall: a careful, fail-closed design that matches the invariants it documents. The catalogue is keyed on vendor rule id (never title or description text), lifts only Suggestions
Tests to add: a related alert with a missing deep verdict, a related alert with rules-only benign triage, and No security blockers found. I'd address 1 and 2 before merge. |
… close check, format-gated catalogue H1: T1531, the Wazuh authentication-failure groups and rules 6250/44733 are credential access. M1: a same-rule sibling is a quiet repeat only when closed as benign or when its own model-close blockers (minus tier and campaign) are empty. L1: the ingestion service records the normalizer format on the canonical alert (kept out of prompts) and the catalogue and repeat count require wazuh. L2-L5: abuse, residual-risk and fail-closed text corrected; non-Wazuh vendors and the max_correlations bound documented. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JmdYVXkgpNHoygVJCrUeZc
Review of PR #345 (FIX-2: noise catalogue and campaign split)I read the diff for the source, the ingestion change, the invariants and the tests. I haven't run the test suite, and the docs and changelog files got only a skim. SummaryThe design is careful. A catalogued rule lifts only Security and policy (INV-03)
Correctness and edge cases
PerformanceEach correlation run evaluates Style and maintainability
TestsCoverage is good. Gaps I'd close:
Nice work on the fail-closed discipline and on documenting the abuse each family could hide. |
…he vendor rule through the state cap A same-rule sibling's own campaign block counts as cleared only when its digest shows no threat, a complete related set and no related alert of another or unknown rule (new digest count related_other_rules); a digest without it is not cleared. cap_alert keeps raw.rule (id, level, description, groups, mitre) when it drops an oversized raw event, and a Wazuh-built alert whose rule cannot be read is the never-close class vendor_unknown. Docs state the deliberate trust in a sibling closed benign by an analyst or approved evidence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JmdYVXkgpNHoygVJCrUeZc
…ut groups lists are vendor_unknown Three review rounds found ways to launder a campaign block through the same-rule repeat count, so the lead dropped it from this PR: _campaign_in_progress, the correlation digest, openapi.json and schema.gen.ts are back to main. Kept: the noise catalogue, T1531 and the Wazuh auth-failure groups as credential access, the raw.rule subset through the state cap, vendor_unknown (now also for a groups list the cap cut) and CanonicalAlert.normalizer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JmdYVXkgpNHoygVJCrUeZc
INV-03 keeps both changes. The verdict-key replay's benign floor moves to 14: Wazuh authentication-failure rules are now a never-close class, so they get no verdict key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JmdYVXkgpNHoygVJCrUeZc
…lasses Wazuh authentication-failure rules outside credential access by ATT&CK are a never-close class since FIX-2, so they get no verdict key: the oracle closes 4 benign corpus_v1 alerts instead of 9, still no attack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JmdYVXkgpNHoygVJCrUeZc
|
Review of FIX-2 (decision policy v2.1). I read the PR description, the docs, closure.py, noise_families.py and the graph.py size-cap change. I did not run the tests. The diff I had was truncated, so I only skimmed routing.py, ingestion/service.py, models/alert.py and the tests. There is no CLAUDE.md in the repo. What looks good:
Issues and suggestions:
Security and performance: I found no injection path in the lookup, which is an exact match on a digit-validated id, and the per-alert cost is negligible. Items 1 and 2 are the only places I found where a never-close gate can fail open, so I would fix those before merge. Otherwise this is a careful, well-documented T3 change. |
FIX-2: decision policy v2.1. Catalogued unmapped noise, and authentication failures as a never-close class
Closes #342. Tier T3: this changes the decision policy and INV-03. Follows #340 and #341.
Scope change after review: the campaign split is deferred. #342 asked for a campaign check that tells one rule repeating apart from an attack. Three independent review rounds each found a way to launder a block through it:
The lead decided to drop it from this PR. FIX-1's campaign check stays exactly as on
main: a burst,related_threatsorrelated_open_reviewsblocks. No new correlation digest fields ship.What changed
Noise catalogue (
src/lg_sotf/domain/noise_families.py, version2026-11-09.2).raw.rule.id, digits only). It counts only when both hold:CanonicalAlert.normalizer, never taken from the event, andmodel_viewkeeps it out of prompts;"<id>: <description>".unmappedclass (closure.model_close_class). Every other check still applies: the tier, severity, both model tiers benign at 8/85, steering text, a recent true positive and FIX-1's campaign check.linux_package_installlogger -t yum), so a repeat can be a decoy.windows_software_installantivirus_statusweb_client_errorThese entries were chosen from the ruleset's meaning, not from corpus labels. For example, 554 and 31120 are benign in parts of corpus_v1 but are left out.
Authentication failures are a never-close class whatever their ATT&CK id (review H1). Each of these counts as
credential_access:authentication_failed,authentication_failures,invalid_loginorlogin_denied;These checks only block, so they read the raw event whatever format built the alert.
State cap (
cap_alert).raw.rule(id, level, description, groups, mitre).vendor_unknown, which also blocks the catalogue lift.groups_truncated.INV-03 text and proofs, plus docs:
threat-model.md(TM-WRK-2, with corrected residual risk),architecture.md,security.md,ai-system-card.md,changelog.d/FIX-2.md, and the closure, routing and catalogue docstrings.CanonicalAlert.normalizeris new. Alerts stored before this release have none, so the catalogue does not apply to them (fail closed).openapi.jsonandschema.gen.tsare unchanged againstmain.Review fixes kept
test_noise_families.py::test_review_h1_*, covering 60122, 60130, 99919, 60196, 5302, 6250 and 44733 through the real Wazuh normalizernormalizerrecorded at ingestion; the catalogue requireswazuhtest_noise_families.py;test_ingest.py::test_a_pushed_event_cannot_claim_the_wazuh_normalizerraw.rulesubset kept;vendor_unknowntest_an_oversized_raw_event_keeps_its_rule_through_the_state_cap,test_recheck_a_wazuh_alert_without_a_readable_rule_never_closes,test_final_a_cut_groups_list_never_closesMeasured (
HEAD)Fake model. Eval harness plus the dataset gates, corpus_v1 replayed from its committed cassettes. No cassette changed.
auto_full_audit: benign closed (95% Wilson CI)auto_full_audit: malicious closedDeepSeek, dev run 2 (100 Wazuh alerts, FIX-1 deployed), simulated with the real
decide, the run's own correlation digests (FIX-1 campaign check) and the raw event from corpus_v1:auto_full_auditwindows_software_install,antivirus_statusBlockers on the 27 benign alerts that reach the model-close check:
never_close_classcampaign_in_progressfast_tier_not_benigndeep_tier_not_benignThe campaign check and the model tiers remain the main blockers. The scorecard corpus_v1 simulation and the fooled-model worst case were not rerun for this scope.
Threat note
logger -t yum, a per-user MSI), and both model tiers are persuaded it is routine.unmapped, and keys on the Wazuh normalizer's rule id, never on text;vendor_unknown;model_closed/ai_closed:audit_requiredand names its family and catalogue version;Merged with
main(verdict cache, #344)Checks
ruff,mypy(375 files),lint-imports(14 kept), changelog check.pytest tests/unit tests/invariants tests/deployafter the merge: 5137 passed.tests/integrationeval, engine and ingestion after the merge: 130 passed, 1 skipped, 1 failed. The failure is the phishing_v1 cassette replay, which fails onmaintoo ([BUG] phishing_v1 cassette replay is time-dependent: 4 items miss after some hours #346, fixed separately). The two oracle tests pass after the floor update.🤖 Generated with Claude Code
https://claude.ai/code/session_01JmdYVXkgpNHoygVJCrUeZc