Skip to content

Commit 58d513d

Browse files
tot19claude
andcommitted
chore(sources): Remove wildcard expansion and message field truncation from Windows Event Log source
- Remove wildcard channel pattern expansion (caused heap corruption with many channels) - Add config validation to explicitly reject wildcard patterns (*, ?, [) with clear error message - Remove max_message_field_length config option (unnecessary complexity) - Clean up unused error variants and helper functions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 02c4572 commit 58d513d

5 files changed

Lines changed: 65 additions & 593 deletions

File tree

‎changelog.d/windows_eventlog_source.feature.md‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,4 @@ This Windows-specific source uses event-driven subscriptions to stream events in
1717
New configuration options:
1818
- `events_per_second`: Rate limit event processing (0 = unlimited)
1919
- `max_event_data_length`: Truncate event data values (0 = no truncation, Winlogbeat default)
20-
- `max_message_field_length`: Truncate message summary field (0 = no truncation, Winlogbeat default)
2120
- `data_dir`: Directory for checkpoint persistence

‎src/sources/windows_eventlog/config.rs‎

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -157,16 +157,6 @@ pub struct WindowsEventLogConfig {
157157
#[configurable(metadata(docs::examples = 4096))]
158158
pub max_event_data_length: usize,
159159

160-
/// Maximum length for message summary field.
161-
///
162-
/// The message field contains a human-readable summary with event data samples.
163-
/// Individual event data values in the message will be truncated to this length.
164-
/// Set to 0 for no limit (matches Winlogbeat behavior).
165-
#[serde(default = "default_max_message_field_length")]
166-
#[configurable(metadata(docs::examples = 256))]
167-
#[configurable(metadata(docs::examples = 1024))]
168-
pub max_message_field_length: usize,
169-
170160
/// Controls how acknowledgements are handled for this source.
171161
///
172162
/// When enabled, the source will wait for downstream sinks to acknowledge
@@ -269,7 +259,6 @@ impl Default for WindowsEventLogConfig {
269259
data_dir: None,
270260
events_per_second: default_events_per_second(),
271261
max_event_data_length: default_max_event_data_length(),
272-
max_message_field_length: default_max_message_field_length(),
273262
acknowledgements: Default::default(),
274263
}
275264
}
@@ -328,11 +317,20 @@ impl WindowsEventLogConfig {
328317
.into());
329318
}
330319

320+
// Reject wildcard patterns - they cause heap corruption issues with many channels
321+
if is_channel_pattern(channel) {
322+
return Err(format!(
323+
"Channel name '{}' contains wildcard characters (*, ?, [). \
324+
Wildcard patterns are not supported. Please specify exact channel names.",
325+
channel
326+
)
327+
.into());
328+
}
329+
331330
// Validate channel name contains only safe characters
332-
// Allow *, ?, [ for glob pattern matching (e.g., "Microsoft-Windows-*")
333331
if !channel
334332
.chars()
335-
.all(|c| c.is_ascii_alphanumeric() || "-_ /\\*?[]".contains(c))
333+
.all(|c| c.is_ascii_alphanumeric() || "-_ /\\".contains(c))
336334
{
337335
return Err(
338336
format!("Channel name '{}' contains invalid characters", channel).into(),
@@ -556,10 +554,6 @@ const fn default_max_event_data_length() -> usize {
556554
0 // 0 means no truncation (matches Winlogbeat)
557555
}
558556

559-
const fn default_max_message_field_length() -> usize {
560-
0 // 0 means no truncation (matches Winlogbeat)
561-
}
562-
563557
#[cfg(test)]
564558
mod tests {
565559
use super::*;
@@ -647,7 +641,6 @@ mod tests {
647641
data_dir: PathBuf::from("/test/data"),
648642
events_per_second: 1000,
649643
max_event_data_length: 0,
650-
max_message_field_length: 0,
651644
acknowledgements: SourceAcknowledgementsConfig::from(true),
652645
};
653646

@@ -691,23 +684,35 @@ mod tests {
691684
}
692685

693686
#[test]
694-
fn test_config_validation_allows_wildcards() {
687+
fn test_config_validation_rejects_wildcards() {
695688
let mut config = WindowsEventLogConfig::default();
696689

697-
// Wildcard patterns should be allowed in channel names
698-
config.channels = vec![
699-
"System".to_string(),
700-
"Microsoft-Windows-*".to_string(),
701-
"Microsoft-Windows-Sysmon/*".to_string(),
702-
];
703-
assert!(config.validate().is_ok());
690+
// Asterisk wildcard should be rejected
691+
config.channels = vec!["Microsoft-Windows-*".to_string()];
692+
let err = config.validate().unwrap_err();
693+
assert!(err.to_string().contains("wildcard"));
704694

705-
// Single character wildcards should work
695+
// Single character wildcards should be rejected
706696
config.channels = vec!["System?".to_string()];
707-
assert!(config.validate().is_ok());
697+
let err = config.validate().unwrap_err();
698+
assert!(err.to_string().contains("wildcard"));
708699

709-
// Character classes should work
700+
// Character classes should be rejected
710701
config.channels = vec!["[Ss]ystem".to_string()];
702+
let err = config.validate().unwrap_err();
703+
assert!(err.to_string().contains("wildcard"));
704+
705+
// Mixed valid and wildcard should be rejected
706+
config.channels = vec!["System".to_string(), "Microsoft-Windows-*".to_string()];
707+
let err = config.validate().unwrap_err();
708+
assert!(err.to_string().contains("wildcard"));
709+
710+
// Exact channel names should still work
711+
config.channels = vec![
712+
"System".to_string(),
713+
"Application".to_string(),
714+
"Microsoft-Windows-Sysmon/Operational".to_string(),
715+
];
711716
assert!(config.validate().is_ok());
712717
}
713718
}

‎src/sources/windows_eventlog/error.rs‎

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,6 @@ pub enum WindowsEventLogError {
5959
#[snafu(display("Channel '{}' not found", channel))]
6060
ChannelNotFoundError { channel: String },
6161

62-
#[snafu(display("Failed to enumerate event log channels: {}", source))]
63-
ChannelEnumerationError {
64-
#[cfg(windows)]
65-
source: windows::core::Error,
66-
#[cfg(not(windows))]
67-
source: Box<dyn std::error::Error + Send + Sync>,
68-
},
69-
70-
#[snafu(display("No channels matched pattern '{}'", pattern))]
71-
NoChannelsMatchedPattern { pattern: String },
72-
7362
#[snafu(display("I/O error: {}", source))]
7463
IoError { source: std::io::Error },
7564

@@ -146,8 +135,6 @@ impl WindowsEventLogError {
146135
| Self::SubscriptionError { .. }
147136
| Self::AccessDeniedError { .. }
148137
| Self::ChannelNotFoundError { .. }
149-
| Self::ChannelEnumerationError { .. }
150-
| Self::NoChannelsMatchedPattern { .. }
151138
| Self::InvalidXPathQuery { .. }
152139
| Self::ConfigError { .. }
153140
| Self::CreateRenderContextError { .. }

0 commit comments

Comments
 (0)