Skip to content

Prevent content from steering the string match filters - #317

Merged
FreeAndNil merged 5 commits into
masterfrom
Feature/317-filters
Sep 4, 2026
Merged

Prevent content from steering the string match filters#317
FreeAndNil merged 5 commits into
masterfrom
Feature/317-filters

Conversation

@FreeAndNil

Copy link
Copy Markdown
Contributor

Three findings, one commit: all three sit in StringMatchFilter, whose Decide
was a near-duplicate of PropertyFilter.Decide, so each defect existed at two
sites. Both now share one implementation, which is also why MdcFilter and
NdcFilter need no change.

  • f018 The substring search was culture sensitive, and a linguistic search
    skips ignorable characters, so content holding a NUL, a soft hyphen or a
    zero-width space between the letters of stringToMatch still matched it, and
    the decision varied with the host culture. Ordinal now, so the filter decides
    the same way a reader of the log would.
  • f017 An abandoned regex match was treated as a non-match. But the content
    decides whether the deadline is reached, so in an AcceptOnMatch allowlist
    ending in a DenyAllFilter, content could suppress its own record. The new
    timeoutDecision decides those events, still Neutral by default; Accept
    makes such a chain fail towards logging.
  • f041 The default matchTimeoutMillis drops from 1000 to 50. The match runs
    under the appender lock, so the deadline bounds what one crafted event costs
    every other logging thread. A legitimate match takes a fraction of that.

filters.adoc documented the old deadline and outcome, and its example set the
value back to 1000; both corrected, and timeoutDecision is documented against
the allowlist arrangement the same page recommends.

Deliberate default change: f041. An operator whose pattern genuinely needs
longer must now set matchTimeoutMillis, and gets the existing once-per-filter
warning if a match is abandoned.

Tests: 13 new across both filters, and each fix was checked by reverting it and
confirming the right tests fail (5 for f018, 3 for f017, 1 for f041).

- Logging an empty message threw IndexOutOfRangeException: the branch meant for
  a one-character message read message[0] without checking there was one.
- AppenderSkeleton caught it, so the event simply disappeared.
- The reset codes now go at one computed offset, leaving no short-message branch
  to get wrong.
- All ten line-break cases are pinned by test. They carry explicit names because
  dotnet test --filter cannot see them otherwise; CLAUDE.md records why.

audit da18b6f-f029
#316

- Reading HttpRequest.Params validates the query string, form and cookies on
  first access, so a request carrying <script> threw inside the layout and
  AppenderSkeleton discarded the whole event: a sender could suppress the log
  record of their own request.
- The converter now reads through HttpRequest.Unvalidated, so the content is
  kept rather than replaced by the not-available marker.
- The try now also covers the body parse and ServerVariables, which throw on an
  oversized body or a lost client. Verified on Windows: with no worker request
  behind it, ServerVariables is empty rather than throwing.
- Five tests, net462 only, so they run on the Windows leg alone. Reverting the
  fix fails exactly the two that assert the content survives.

audit da18b6f-f019
CLAUDE.md wants the description to close with both sides, who raised it and who
did the work. Eleven entries named only the audit finding. Nothing but the
attribution changed.
The Ext.Mail send rework answers f004 and the remote syslog queue and pump work
answers f034, but neither pair named the finding. The other five 314 and 315
entries stay unattributed: they are our own, not audit findings.
- Substring matching was culture sensitive, so a NUL, soft hyphen or
  zero-width space inside StringToMatch still matched. Ordinal now.
- An abandoned regex match counted as a non-match, so content that
  forced the timeout could suppress its own record. TimeoutDecision
  decides it, still Neutral by default.
- Default deadline 1000ms to 50ms. The match holds the appender lock.
- StringMatchFilter and PropertyFilter had near-identical Decide
  bodies, which is why each finding existed twice. Shared now.
- filters.adoc documented the old deadline and outcome, and had an
  example restoring the old default. MdcFilter and NdcFilter derive
  from PropertyFilter and need no change.

audit da18b6f-f017, da18b6f-f018, da18b6f-f041
@FreeAndNil FreeAndNil added this to the 3.5.0 milestone Sep 3, 2026
@FreeAndNil FreeAndNil changed the title Prevent content from steering the string match filters (#317) Prevent content from steering the string match filters Sep 3, 2026
@FreeAndNil
FreeAndNil marked this pull request as ready for review September 4, 2026 11:50
@FreeAndNil
FreeAndNil changed the base branch from master to Feature/2.x September 4, 2026 11:51
@FreeAndNil
FreeAndNil changed the base branch from Feature/2.x to master September 4, 2026 11:51
@FreeAndNil
FreeAndNil merged commit 9c93a34 into master Sep 4, 2026
3 checks passed
@FreeAndNil
FreeAndNil deleted the Feature/317-filters branch September 4, 2026 20:46
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