Skip to content

test(eventviewerx): ✅ guard known-field string literals in rules#241

Merged
PrzemyslawKlys merged 1 commit intomasterfrom
codex/eventviewerx-typed-rollout-phase9
Mar 5, 2026
Merged

test(eventviewerx): ✅ guard known-field string literals in rules#241
PrzemyslawKlys merged 1 commit intomasterfrom
codex/eventviewerx-typed-rollout-phase9

Conversation

@PrzemyslawKlys
Copy link
Member

No description provided.

Copilot AI review requested due to automatic review settings March 5, 2026 10:19
@PrzemyslawKlys PrzemyslawKlys merged commit b4511c9 into master Mar 5, 2026
4 checks passed
@PrzemyslawKlys PrzemyslawKlys deleted the codex/eventviewerx-typed-rollout-phase9 branch March 5, 2026 10:19
@claude
Copy link

claude bot commented Mar 5, 2026

Claude finished @PrzemyslawKlys's task —— View job


Code Review Analysis

Reviewing the merged PR for code quality, best practices, potential issues, and test coverage.

Todo List:

  • Read repository guidelines (CLAUDE.md)
  • Examine the changed test file
  • Analyze code quality and best practices
  • Check for potential bugs or issues
  • Evaluate performance considerations
  • Assess security concerns
  • Review test coverage and effectiveness
  • Provide comprehensive feedback

Review Summary

This PR adds excellent static analysis tests that enforce coding standards for rule source files. The implementation demonstrates strong understanding of defensive programming principles.

✅ Code Quality & Best Practices

Strengths:

  • Excellent architectural pattern: Uses static analysis to enforce coding standards at build time
  • Comprehensive regex patterns: Well-crafted patterns that correctly identify forbidden usage patterns
  • Good separation of concerns: Clean helper methods with single responsibilities
  • Proper error handling: Descriptive assertion messages with offender details
  • Smart comment filtering: Correctly ignores commented code (lines 95-100)
  • Immutable design: Uses IReadOnlyList<string> for field definitions

Minor suggestions:

  • Consider extracting regex patterns as static readonly fields for better performance and maintainability
  • The KnownFieldKeys array could be derived from the KnownEventField enum to ensure consistency

✅ Test Coverage & Effectiveness

Comprehensive rule enforcement:

  1. Direct indexer prevention (TestRuleSourceGuards.cs:40-50): Prevents _eventObject.Data[...] usage
  2. TryGetValue prevention (TestRuleSourceGuards.cs:53-63): Blocks direct dictionary access
  3. String literal prevention (TestRuleSourceGuards.cs:66-80): Enforces typed enum usage over string literals

Strong implementation details:

  • Tests all known field names from the hardcoded list against actual codebase
  • Provides clear failure messages with file paths and line numbers
  • Covers edge cases like whitespace and comment filtering

✅ Performance Considerations

Efficient approach:

  • Compiled regex patterns for better performance (RegexOptions.Compiled)
  • Single-pass file processing with early termination on comment detection
  • Reasonable directory traversal scope (only Rules directory)

Potential optimizations:

  • Consider caching compiled regex patterns as static fields if tests run frequently
  • Current approach is appropriate for test scenarios

✅ Security Concerns

No security issues identified:

  • File system access is properly scoped to the Rules directory
  • Path traversal is handled safely with Path.GetRelativePath
  • No external input processing or dynamic code generation

✅ Architecture Alignment

Excellent integration with existing codebase:

  • Enforces use of typed accessors (KnownEventField enum) over string literals
  • Prevents dangerous direct dictionary access patterns
  • Promotes consistent API usage across rule implementations
  • Tests verify the typed accessor methods exist: TryGetDataValue(KnownEventField), GetDataValueOrEmpty(KnownEventField)

🔍 Observations

Test vs Implementation sync:
The hardcoded KnownFieldKeys array in the test perfectly matches the KnownEventField enum values, ensuring comprehensive coverage of all known fields.

Example enforcement:

// ❌ Blocked by tests
e.GetDataValueOrEmpty("SubjectUserName")
e.TryGetDataValue("TargetSid", out var sid)

// ✅ Enforced pattern  
e.GetDataValueOrEmpty(KnownEventField.SubjectUserName)
e.TryGetDataValue(KnownEventField.TargetSid, out var sid)

Final Assessment

This is a well-implemented static analysis test suite that effectively enforces coding standards and prevents common anti-patterns. The code quality is high, with no security concerns and good performance characteristics. The tests provide excellent coverage for their intended purpose of maintaining code consistency across rule implementations.

Rating: ✅ Excellent - Ready for production with strong defensive programming practices.


Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a010f93fa8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


public class TestRuleSourceGuards
{
private static readonly IReadOnlyList<string> KnownFieldKeys = new[]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cover all KnownEventField keys in literal guard

The new guard hard-codes KnownFieldKeys but omits existing KnownEventField members (Message, NoNameA0, NoNameA1, and TextPayload from Sources/EventViewerX/Definitions/KnownEventField.cs), so string-literal access to those canonical fields is not detected. I verified this gap by searching current rules, which already contain calls like GetValueFromDataDictionary("NoNameA0") and GetValueFromDataDictionary("#text"); this test still passes despite those known-field literals.

Useful? React with 👍 / 👎.

{
string knownKeysPattern = string.Join("|", KnownFieldKeys.Select(Regex.Escape));
Regex knownFieldLiteralPattern = new(
$@"\b(?:GetValueFromDataDictionary|GetDataValueOrEmpty|TryGetDataValue|TryGetDataEnum)\s*\([^)]*""(?:{knownKeysPattern})""",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle multiline accessor calls in regex guard

The pattern \s*\([^)]*"..." is applied to one line at a time, so it only catches calls where the method name and string literal are on the same line. A multiline form (for example, GetDataValueOrEmpty( on one line and the known key string on the next) will bypass this test entirely, which makes the new guard easy to evade through formatting.

Useful? React with 👍 / 👎.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an additional guard test in the EventViewerX test suite to prevent rule source files from using string literals for “known” event field keys when calling EventObject accessor methods (encouraging the KnownEventField enum instead).

Changes:

  • Add KnownFieldKeys list for known event-field key strings.
  • Add a new [Fact] that searches rule source code for accessor calls using those keys as string literals.
  • Add System.Linq for building the dynamic regex pattern.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

{
string knownKeysPattern = string.Join("|", KnownFieldKeys.Select(Regex.Escape));
Regex knownFieldLiteralPattern = new(
$@"\b(?:GetValueFromDataDictionary|GetDataValueOrEmpty|TryGetDataValue|TryGetDataEnum)\s*\([^)]*""(?:{knownKeysPattern})""",
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The offender detection only tests each source line individually (FindRuleSourceOffenders uses File.ReadAllLines + pattern.IsMatch(line)), but this regex requires the method call and the string literal to appear on the same line. Multi-line accessor calls won’t be detected (e.g., Sources/EventViewerX/Rules/AzureAD/AADConnectStagingDisabled.cs uses GetValueFromDataDictionary(\n "SubjectUserName", ...)). Consider scanning the full file text (or buffering a statement until ')' / ';') so the guard also catches multi-line invocations, while still reporting an accurate line number for the match.

Suggested change
$@"\b(?:GetValueFromDataDictionary|GetDataValueOrEmpty|TryGetDataValue|TryGetDataEnum)\s*\([^)]*""(?:{knownKeysPattern})""",
$@"""(?:{knownKeysPattern})""",

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +37
private static readonly IReadOnlyList<string> KnownFieldKeys = new[]
{
"SubjectUserName",
"SubjectDomainName",
"SubjectLogonId",
"TargetUserName",
"TargetDomainName",
"TargetSid",
"WorkstationName",
"IpAddress",
"IpPort",
"LogonType",
"Status",
"SubStatus",
"FailureReason",
"AuthenticationPackageName",
"LogonProcessName",
"LmPackageName",
"KeyLength",
"ProcessId",
"ProcessName",
"TransmittedServices",
"TicketOptions",
"TicketEncryptionType",
"PreAuthType"
};
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KnownFieldKeys duplicates KnownEventField values but is manually maintained and currently omits enum-backed keys like Message/NoNameA0/NoNameA1 and the TextPayload mapping ("#text"). This can lead to false negatives (e.g., Rules/RuleHelpers.cs uses "NoNameA0" and "#text" as string literals). To avoid drift, build the key set from KnownEventField (Enum.GetValues/Enum.GetNames) and include the special ToEventFieldKey mapping for TextPayload.

Copilot uses AI. Check for mistakes.
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.

2 participants