Using contains_cs for Case-Sensitive Searches
Sometimes a normal text search is too broad.
The word matches.
But the casing does not.
And in an investigation, that small difference can matter.
A command, filename, process argument or indicator may appear with a very specific uppercase and lowercase pattern.
In this Agent Foskett Academy lesson, you will learn how defenders use the KQL contains_cs operator to perform case-sensitive searches across Microsoft Defender XDR and Microsoft Sentinel telemetry.
Lesson overview
Learn when case-sensitive searching helps reduce noise and find exact text patterns during Microsoft security investigations.
Why contains_cs matters
That means it can match text even when the uppercase and lowercase letters are different.
Most of the time, that is helpful. But sometimes an investigation needs a more precise search. The contains_cs operator checks whether a field contains a specific value with the same casing.
Investigation scenario
A normal search for encoded commands returns too much noise because different scripts and tools use similar words.
The analyst wants to search for a specific case-sensitive command argument so the result set is tighter and easier to review.
Step 1 — Start with a normal contains search
- 1
- 2
- 3
- 4
- 5
- 6
- 7
DeviceProcessEvents | where Timestamp > ago(7d) | where FileName == "powershell.exe" | where ProcessCommandLine contains "EncodedCommand" | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine
Step 2 — Use contains_cs for exact casing
- 1
- 2
- 3
- 4
- 5
- 6
- 7
DeviceProcessEvents | where Timestamp > ago(7d) | where FileName == "powershell.exe" | where ProcessCommandLine contains_cs "EncodedCommand" | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine
Step 3 — Search for specific command casing
- 1
- 2
- 3
- 4
- 5
- 6
DeviceProcessEvents | where Timestamp > ago(30d) | where ProcessCommandLine contains_cs "DownloadString" | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine | sort by Timestamp desc
What contains_cs does
If you search for DownloadString, it will not match every variation of that word with different casing. This can be useful when you are looking for a very specific pattern.
Step 4 — Find exact file path text
- 1
- 2
- 3
- 4
- 5
- 6
DeviceFileEvents | where Timestamp > ago(14d) | where FolderPath contains_cs "Temp\\Update" | project Timestamp, DeviceName, ActionType, FileName, FolderPath, InitiatingProcessCommandLine | sort by Timestamp desc
Step 5 — Compare suspicious script names
- 1
- 2
- 3
- 4
- 5
- 6
DeviceProcessEvents | where Timestamp > ago(30d) | where ProcessCommandLine contains_cs "Invoke-UpdateCheck.ps1" | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine | sort by Timestamp desc
Step 6 — Use contains_cs with parameters
- 1
- 2
- 3
- 4
- 5
- 6
- 7
let searchText = "EncodedCommand"; DeviceProcessEvents | where Timestamp > ago(7d) | where ProcessCommandLine contains_cs searchText | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine | sort by Timestamp desc
Investigator notes
Do not use it everywhere by default. Attackers can change casing easily, and a case-sensitive search may miss useful evidence if you are still exploring broadly.
What you learned
Continue your investigation
Continue learning with Using in to Search Multiple Indicators, Using let Statements, KQL Threat Hunting Guide and Microsoft Security.
Develop IT. Protect IT. GEMXIT PTY LTD | GEMXIT UK LTD