// question

On a Windows device, there’s evidence that PowerShell history was wiped by deleting the history file. What was the exact command used to perform this action?

Reference KQL answer and model-by-model comparison.

da75ae8d-26d6-4483-b0fe-700e4df4f037
question id
7/23
models correct
1
valid answer
30%
success rate
// reference answer

Human-validated correct answer for this question.

Remove-Item (Get-PSReadlineOption).HistorySavePath
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
no answer
no query generatedfail50.00s0.0202
gpt-35-turbo
no answer
no query generatedfail50.00s0.0110
gpt-4-turbo-2024-04-09
no answer
no query generatedfail50.00s0.2417
gpt-4.1
no answer
no query generatedfail50.00s0.0465
gpt-4.1-finetuned
no answer
no query generatedfail50.00s0.0250
gpt-4.1-mini
Remove-Item (Get-PSReadlineOption).HistorySavePath
DeviceProcessEvents
| where FileName contains "powershell" or InitiatingProcessFileName contains "powershell"
| where ProcessCommandLine contains "Remove-Item" or ProcessCommandLine contains "del" or ProcessCommandLine contains "rm" or ProcessCommandLine contains "RemoveItem"
| where ProcessCommandLine contains ".ps1_history" or ProcessCommandLine contains "ConsoleHost_history.txt" or ProcessCommandLine contains "history"
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine
| order by TimeGenerated desc
pass13.43s0.0022
gpt-4.1-nano
no answer
no query generatedfail50.00s0.0016
gpt-4o
Remove-Item (Get-PSReadlineOption).HistorySavePath
DeviceProcessEvents
| where ProcessCommandLine has_any ('Remove-Item', 'PowerShell_history.txt')
pass122.86s0.0618
gpt-5-high
"powershell.exe" & {Remove-Item (Get-PSReadlineOption).HistorySavePath}
let historyFile = "ConsoleHost_history.txt";
let psReadLineFolderHint = @"\PSReadLine\";
let historyPathRegex = @"(?i)\\Microsoft\\(Windows\\PowerShell|PowerShell)\\PSReadLine\\ConsoleHost_history\.txt$";
let deleteCmdRegex = @"(?i)\b(del(\.exe)?|erase|remove-item|rm|\[System\.IO\.File\]::Delete)\b";
// Primary: file deletion telemetry with initiating process command line
let fileDeleted =
    DeviceFileEvents
    | where ActionType == "FileDeleted"
    | extend TargetFilePath = strcat(FolderPath, "\\", FileName)
    | where FileName =~ historyFile
        or TargetFilePath matches regex historyPathRegex
        or FolderPath has psReadLineFolderHint
    | project TimeGenerated, DeviceName, DeviceId,
              AccountName=InitiatingProcessAccountName,
              InitiatingProcessFileName, ExactCommand=InitiatingProcessCommandLine,
              TargetFilePath, Evidence="DeviceFileEvents";
// Fallback: if DeviceFileEvents is sparse on this device
let fileDeletedFallback =
    DeviceEvents
    | where ActionType == "FileDeleted"
    | extend TargetFilePath = strcat(FolderPath, "\\", FileName)
    | where FileName =~ historyFile
        or TargetFilePath matches regex historyPathRegex
        or FolderPath has psReadLineFolderHint
    | project TimeGenerated, DeviceName, DeviceId,
              AccountName=InitiatingProcessAccountName,
              InitiatingProcessFileName, ExactCommand=InitiatingProcessCommandLine,
              TargetFilePath, Evidence="DeviceEvents";
// Last resort: commands that explicitly delete the PSReadLine history file (literal path or via Get-PSReadLineOption)
let procDelete =
    DeviceProcessEvents
    | where FileName in~ ("powershell.exe","pwsh.exe","cmd.exe","powershell_ise.exe")
    | where ProcessCommandLine matches regex deleteCmdRegex
    | where ProcessCommandLine contains historyFile
        or ProcessCommandLine contains "(Get-PSReadLineOption).HistorySavePath"
        or ProcessCommandLine contains "(Get-PSReadlineOption).HistorySavePath"
        or (ProcessCommandLine contains psReadLineFolderHint and (ProcessCommandLine contains "\\Microsoft\\Windows\\PowerShell" or ProcessCommandLine contains "\\Microsoft\\PowerShell" or ProcessCommandLine contains "$env:APPDATA" or ProcessCommandLine contains "%APPDATA%"))
    | project TimeGenerated, DeviceName, DeviceId,
              AccountName,
              InitiatingProcessFileName=FileName,
              ExactCommand=ProcessCommandLine,
              TargetFilePath="",
              Evidence="DeviceProcessEvents";
fileDeleted
| union fileDeletedFallback
| union procDelete
| order by TimeGenerated desc
pass2173.35s0.1092
gpt-5-mini-high
"powershell.exe" & {Remove-Item (Get-PSReadlineOption).HistorySavePath}
// Find deletions of the PSReadLine (PowerShell) history file and the process command that performed the action
let fileDeletes = DeviceFileEvents
| where tolower(FileName) contains "consolehost_history" or tolower(FolderPath) contains "psreadline"
| where tolower(ActionType) contains "delete" or tolower(ActionType) contains "removed" or tolower(ActionType) contains "remove"
| project TimeGenerated, Source = "DeviceFileEvents", DeviceName, Account = InitiatingProcessAccountName, FileName, FolderPath, ActionType, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId;

let procDeletes = DeviceProcessEvents
| where tolower(ProcessCommandLine) contains "consolehost_history" or tolower(ProcessCommandLine) contains "psreadline"
| where ProcessCommandLine matches regex @"(?i)\b(remove-item|remove|del|erase|rm|clear-content|icm|Remove-Item)\b"
| project TimeGenerated, Source = "DeviceProcessEvents", DeviceName, Account = AccountName, FileName = InitiatingProcessFileName, FolderPath = InitiatingProcessFolderPath, ActionType = tostring("") , InitiatingProcessFileName = InitiatingProcessFileName, InitiatingProcessCommandLine = ProcessCommandLine, InitiatingProcessId = ProcessId;

union fileDeletes, procDeletes
| sort by TimeGenerated desc
| take 100
| project TimeGenerated, Source, DeviceName, Account, FileName, FolderPath, ActionType, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId
pass128.81s0.0070
gpt-5-mini-low
no answer
no query generatedfail50.00s0.0277
gpt-5-mini-medium
no answer
no query generatedfail50.00s0.0191
gpt-5-nano-high
no answer
no query generatedfail50.00s0.0096
gpt-5-nano-medium
no answer
no query generatedfail50.00s0.0071
grok-3-beta
no answer
no query generatedfail50.00s0.0974
grok-3-mini-beta
Remove-Item (Get-PSReadlineOption).HistorySavePath
DeviceProcessEvents
| where InitiatingProcessFileName has 'powershell.exe'
| where ProcessCommandLine has 'Remove-Item'
| where ProcessCommandLine has_any ('history.txt', 'ConsoleHost_history.txt', 'PowerShell')
| project Timestamp, DeviceName, ProcessCommandLine
| order by Timestamp desc
pass444.16s0.0062
o1-high
no answer
no query generatedfail50.00s0.6903
o1-low
powershell.exe & {Remove-Item (Get-PSReadlineOption).HistorySavePath}
DeviceProcessEvents
| where (
    (ProcessCommandLine contains "history" and (ProcessCommandLine contains "del" or ProcessCommandLine contains "remove-item" or ProcessCommandLine contains "rm" or ProcessCommandLine contains "erase" or ProcessCommandLine contains "System.IO.File"))
    or (InitiatingProcessCommandLine contains "history" and (InitiatingProcessCommandLine contains "del" or InitiatingProcessCommandLine contains "remove-item" or InitiatingProcessCommandLine contains "rm" or InitiatingProcessCommandLine contains "erase" or InitiatingProcessCommandLine contains "System.IO.File"))
    or (ProcessCommandLine has_any ("ConsoleHost_history","PSReadLineHistory") and ProcessCommandLine has_any ("del","remove-item","rm","erase"))
    or (InitiatingProcessCommandLine has_any ("ConsoleHost_history","PSReadLineHistory") and InitiatingProcessCommandLine has_any ("del","remove-item","rm","erase"))
)
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessCommandLine
| order by TimeGenerated desc
pass392.42s0.6712
o3-high
Remove-Item
// --- Detect Power-Shell history wiping by deletion of the PSReadLine history file
// --- and surface the exact command that executed the action.
// --- Time range is supplied by the hunting UI / calling function.
// -----------------------------------------------------------------------------
// 1)  Identify concrete evidence that the file ConsoleHost_history.txt was deleted
//     (Defender for Endpoint produces this in DeviceFileEvents or DeviceEvents)
let HistoryFile      = "ConsoleHost_history.txt";
let DeleteActionList = dynamic(["FileDeleted","FileDeleteCompleted","FileRemoved","DeleteFile"]);
let DeletionEvidence = union isfuzzy=true
        (DeviceFileEvents | where ActionType in (DeleteActionList)),
        (DeviceEvents     | where ActionType in (DeleteActionList))
    | where FileName =~ HistoryFile                              // exact file name
      and FolderPath has "\\PowerShell\\PSReadLine"             // typical parent folder
    | project DelTime = TimeGenerated,
              DeviceId,
              DeviceName,
              FolderPath,
              InitiatingProcessId,
              DeletingProcess   = InitiatingProcessFileName,
              DeletingCmdLine   = InitiatingProcessCommandLine,
              DeletingUser      = strcat(InitiatingProcessAccountDomain,'\\',InitiatingProcessAccountName);

// 2)  Look for any command line (PowerShell, pwsh, or cmd) that references either
//     the history file path itself *or* the PowerShell variable that resolves to it,
//     together with deletion verbs (Remove-Item / del / Clear-History …).
//     This complements the sparse file–level telemetry on some endpoints.
let DeleteVerbRegex = @"(?i)(del|erase|remove-?item|rm|clear-history|copy\s+nul|type\s+nul\s*>|set-content)";
let CmdEvidence = DeviceProcessEvents
    | where FileName in~ ("powershell.exe","pwsh.exe","cmd.exe","powershell_ise.exe")
    | where ProcessCommandLine has_any ("PSReadLine","HistorySavePath",HistoryFile)
    | where ProcessCommandLine matches regex DeleteVerbRegex
    | project CmdTime  = TimeGenerated,
              DeviceId,
              DeviceName,
              ProcessId,
              CmdExe   = FileName,
              ExactCommand = ProcessCommandLine,
              CmdUser  = strcat(AccountDomain,'\\',AccountName);

// 3)  (Optional but very useful) For hosts with PowerShell logging enabled, hunt the
//     dedicated PowerShellCommand events – they often contain the verbatim script text.
let PSCommandEvidence = DeviceEvents
    | where ActionType == "PowerShellCommand"
    | extend PSCommand = tostring(parse_json(AdditionalFields).Command)
    | where PSCommand has_any ("PSReadLine","HistorySavePath",HistoryFile)
    | where PSCommand matches regex DeleteVerbRegex
    | project CmdTime  = TimeGenerated,
              DeviceId,
              DeviceName,
              ProcessId          = InitiatingProcessId,
              CmdExe             = InitiatingProcessFileName,
              ExactCommand       = PSCommand,
              CmdUser            = strcat(InitiatingProcessAccountDomain,'\\',InitiatingProcessAccountName);

// 4)  Combine all command-line evidence and correlate it (same device and very close
//     in time) with the confirmed file-deletion telemetry when such telemetry exists.
union CmdEvidence, PSCommandEvidence
| join kind=leftouter (
        DeletionEvidence
) on DeviceId
| where isnull(DelTime)                                   // keep rows without explicit delete event
      or abs(datetime_diff('minute', DelTime, CmdTime)) <= 5 // …or correlate within ±5 minutes
      or ProcessId == InitiatingProcessId                   // …or same PID
| project EventTime     = coalesce(DelTime, CmdTime),
          DeviceName,
          User          = coalesce(DeletingUser, CmdUser),
          CommandUsed   = coalesce(ExactCommand, DeletingCmdLine),
          Executable    = CmdExe,
          FolderPath,
          EvidenceType  = iff(isnotempty(DelTime), "FileDelete", "CommandLineOnly")
| order by EventTime desc
fail3183.52s0.0870
o3-mini-high
no answer
no query generatedfail50.00s0.0403
o3-mini-low
no answer
no query generatedfail50.00s0.0430
o4-mini-high
"powershell.exe" & {Remove-Item (Get-PSReadlineOption).HistorySavePath}
// 1) Find explicit file-deletion events for the PSReadLine history file
let FileDeletes = DeviceFileEvents
| where ActionType == "FileDeleted"
| where FileName endswith "ConsoleHost_history.txt"
| where FolderPath contains "PSReadLine"
| where InitiatingProcessFileName in ("powershell.exe","pwsh.exe")
| project TimeGenerated, DeviceName, Account = InitiatingProcessAccountName, Command = InitiatingProcessCommandLine;

// 2) Find PowerShell process executions that reference the history file with delete/clear cmdlets
let ProcessDeletes = DeviceProcessEvents
| where FileName in ("powershell.exe","pwsh.exe")
| where ProcessCommandLine matches regex @"(?i)\b(remove-?item|del|erase|rm|clear-?content)\b"
| where ProcessCommandLine contains "HistorySavePath" or ProcessCommandLine contains "ConsoleHost_history"
| project TimeGenerated, DeviceName, Account = AccountName, Command = ProcessCommandLine;

// Combine, dedupe, and sort to get the exact command used to wipe the history
union FileDeletes, ProcessDeletes
| sort by TimeGenerated asc
| distinct TimeGenerated, DeviceName, Account, Command
| project Timestamp = TimeGenerated, DeviceName, Account, Command
pass5157.45s0.0562
o4-mini-low
no answer
no query generatedfail50.00s0.0403