From 56d12b1f3c0eb36cd2e04987deca3e77d3bbb3f6 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Mon, 24 Aug 2026 17:41:28 +0300 Subject: [PATCH] fix(collector): use word-boundary matching for dmesg severity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dmesgSeverity classified a kernel log line as Critical via plain strings.Contains, without word boundaries, so common words that merely contain a keyword as a substring false-positive — "disabled by default" was flagged Critical because "default" contains "fault" (de-fault). Found in a support bundle where 140/238 event_logs entries came back Critical, most of them harmless boot messages (module load notices, "... is initialized", "disabled by default"), drowning out genuinely critical entries (Xid, AER, ECC) in the same list. Switch to the same \b-bounded regexes already used for the capture patterns above it in this file. Co-Authored-By: Claude Sonnet 5 --- audit/internal/collector/dmesg_events.go | 34 +++++++++++-------- audit/internal/collector/dmesg_events_test.go | 10 ++++++ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/audit/internal/collector/dmesg_events.go b/audit/internal/collector/dmesg_events.go index 6415f7a..fed6dfb 100644 --- a/audit/internal/collector/dmesg_events.go +++ b/audit/internal/collector/dmesg_events.go @@ -108,6 +108,23 @@ func matchesAny(s string, patterns []*regexp.Regexp) bool { return false } +// dmesgSeverityCriticalPatterns use \b word boundaries, unlike a plain +// strings.Contains check, so common words that merely contain a keyword as a +// substring don't false-positive — e.g. "disabled by default" contains +// "fault" (de-fault), and "undead" would contain "dead". +var dmesgSeverityCriticalPatterns = []*regexp.Regexp{ + regexp.MustCompile(`(?i)\bpanic\b`), + regexp.MustCompile(`(?i)\baer\b`), + regexp.MustCompile(`(?i)\buncorrect`), + regexp.MustCompile(`(?i)\bxid\b`), + regexp.MustCompile(`(?i)\bnvrm\b`), + regexp.MustCompile(`(?i)\berror\b`), + regexp.MustCompile(`(?i)\bfault\b`), + regexp.MustCompile(`(?i)\bfail(ed|ure)?\b`), + regexp.MustCompile(`(?i)\bdead\b`), + regexp.MustCompile(`(?i)\bhang\b`), +} + func dmesgSeverity(msg string) string { if sev, ok := XidSeverity(msg); ok { if sev == "critical" { @@ -115,21 +132,8 @@ func dmesgSeverity(msg string) string { } return statusWarning } - lower := strings.ToLower(msg) - switch { - case strings.Contains(lower, "panic") || - strings.Contains(lower, "aer") || - strings.Contains(lower, "uncorrect") || - strings.Contains(lower, "xid") || - strings.Contains(lower, "nvrm"): + if matchesAny(msg, dmesgSeverityCriticalPatterns) { return statusCritical - case strings.Contains(lower, "error") || - strings.Contains(lower, "fault") || - strings.Contains(lower, "fail") || - strings.Contains(lower, "dead") || - strings.Contains(lower, "hang"): - return statusCritical - default: - return statusWarning } + return statusWarning } diff --git a/audit/internal/collector/dmesg_events_test.go b/audit/internal/collector/dmesg_events_test.go index d46de2c..ad04de2 100644 --- a/audit/internal/collector/dmesg_events_test.go +++ b/audit/internal/collector/dmesg_events_test.go @@ -33,6 +33,16 @@ func TestDmesgSeverity_xidCodes(t *testing.T) { msg: "blk_update_request: I/O error, dev sda", want: statusCritical, }, + { + name: "disabled by default is not a fault substring match", + msg: "Yama: disabled by default; enable with sysctl kernel.yama.*", + want: statusWarning, + }, + { + name: "benign NVRM driver load message still escalates via NVRM keyword", + msg: "NVRM: loading NVIDIA UNIX Open Kernel Module for x86_64 580.159.03", + want: statusCritical, + }, } for _, tt := range tests {