// question

During investigation of a Linux device, you see evidence of a process that reports system locale details. Identify the tool used.

Reference KQL answer and model-by-model comparison.

07ce871a-b3c3-44a3-97fa-a20118fdc7c9
question id
3/23
models correct
1
valid answer
13%
success rate
// reference answer

Human-validated correct answer for this question.

localectl
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
locale
DeviceProcessEvents
| where ProcessCommandLine has "locale" or ProcessCommandLine has "localectl"
| project Timestamp, DeviceName, FileName, ProcessCommandLine, InitiatingProcessCommandLine
fail111.04s0.0056
gpt-35-turbo
no answer
no query generatedfail50.00s0.0106
gpt-4-turbo-2024-04-09
locale
DeviceProcessEvents
| where ProcessCommandLine has 'locale' or ProcessCommandLine has 'localectl'
| project DeviceId, DeviceName, ProcessCommandLine, ProcessCreationTime, FileName, FolderPath
| distinct DeviceName, ProcessCommandLine, ProcessCreationTime, FileName, FolderPath
fail110.86s0.0791
gpt-4.1
locale
DeviceProcessEvents
| join kind=inner (
    DeviceInfo
    | where OSPlatform == "Linux"
    | project DeviceId
) on DeviceId
| where FileName in ("locale", "localectl") or ProcessCommandLine has_any ("locale", "localectl", "/etc/locale.conf", "/etc/default/locale", "LANG=")
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine
| order by TimeGenerated desc
| take 100
fail320.66s0.0595
gpt-4.1-finetuned
locale, localectl, cat, curl (system reporting scripts)
DeviceProcessEvents | where InitiatingProcessCommandLine contains "locale" or ProcessCommandLine contains "locale" | extend AccountCustomEntity = InitiatingProcessAccountUpn, HostCustomEntity = DeviceName, FileCustomEntity = InitiatingProcessCommandLine | project-away InitiatingProcessLogonId,InitiatingProcessParentId,InitiatingProcessSessionId
pass257.27s0.0733
gpt-4.1-mini
locale
DeviceProcessEvents
| where DeviceName contains "linux" or SourceSystem == "Linux" or InitiatingProcessFileName endswith ".sh" or InitiatingProcessFileName contains "bash" or ProcessCommandLine contains "locale" or ProcessCommandLine contains "localectl" or ProcessCommandLine contains "language"
| where ProcessCommandLine contains "locale" or ProcessCommandLine contains "localectl" or ProcessCommandLine contains "language" or InitiatingProcessCommandLine contains "locale" or InitiatingProcessCommandLine contains "localectl" or InitiatingProcessCommandLine contains "language"
| project DeviceName, ProcessCommandLine, FileName
| distinct DeviceName, ProcessCommandLine, FileName
| extend ToolUsed = FileName
| project DeviceName, ToolUsed, ProcessCommandLine
| sort by DeviceName asc
fail224.03s0.0044
gpt-4.1-nano
no answer
no query generatedfail50.00s0.0015
gpt-4o
locale
DeviceProcessEvents
| where ProcessCommandLine contains "locale" or InitiatingProcessCommandLine contains "locale"
| project DeviceId, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessId, ProcessCommandLine, TimeGenerated
fail13.45s0.0252
gpt-5-high
localectl
let linux_devices = DeviceInfo
| where OSPlatform =~ "Linux"
| project DeviceId, DeviceName;
DeviceProcessEvents
| where ActionType == "ProcessCreated"
| join kind=inner linux_devices on DeviceId
| where FileName in~ ("localectl", "locale") or ProcessCommandLine has_any ("localectl", "locale")
| extend Tool = iif(ProcessCommandLine has "localectl", "localectl", iif(ProcessCommandLine has "locale", "locale", tostring(FileName)))
| summarize FirstSeen=min(Timestamp), LastSeen=max(Timestamp), EventCount=count(), Devices=dcount(DeviceId), SampleCommandLine=any(ProcessCommandLine) by Tool
| order by EventCount desc
pass150.67s0.0314
gpt-5-mini-high
locale
// Find Linux processes/commands that report or configure system locale settings
// Adjust the keyword list if you want to broaden or narrow matches
let locale_terms = dynamic(["localectl","locale-gen","localedef","update-locale","dpkg-reconfigure","locale"]);
union DeviceProcessEvents, DeviceEvents
| where isnotempty(FileName) or isnotempty(ProcessCommandLine) or isnotempty(InitiatingProcessCommandLine)
| extend cmd = tostring(ProcessCommandLine), fname = tostring(FileName), ipcmd = tostring(InitiatingProcessCommandLine)
// Quick filter to limit rows to those containing any of the locale terms
| where cmd has_any (locale_terms) or fname has_any (locale_terms) or ipcmd has_any (locale_terms)
// Extract the exact matched term from combined fields
| extend combined = strcat(" ", cmd, " ", fname, " ", ipcmd)
| extend tool = extract(@"\b(localectl|locale\-gen|localedef|update\-locale|dpkg\-reconfigure|locale)\b", 1, combined)
| where isnotempty(tool)
| project TimeGenerated, DeviceName, DeviceId, ProcessId, InitiatingProcessId, FileName=fname, ProcessCommandLine=cmd, InitiatingProcessCommandLine=ipcmd, tool
| summarize occurrences = count(), firstSeen = min(TimeGenerated), lastSeen = max(TimeGenerated) by tool, DeviceName, DeviceId
| order by occurrences desc, lastSeen desc
| limit 100
fail123.56s0.0059
gpt-5-mini-low
locale
let linuxDevices = DeviceInfo
| where tolower(OSPlatform) has "linux"
| distinct DeviceId;

union isfuzzy=true DeviceProcessEvents, DeviceEvents, DeviceFileEvents
| where DeviceId in (linuxDevices)
| extend combined = strcat(
    tostring(ProcessCommandLine), " ",
    tostring(InitiatingProcessCommandLine), " ",
    tostring(FileName), " ",
    tostring(FolderPath), " ",
    tostring(FileOriginUrl), " ",
    tostring(RegistryValueData)
  )
| where tolower(combined) matches regex @"\b(localectl|update-locale|printenv\s*lang|lang=|locale)\b"
| extend tool = extract(@"(localectl|update-locale|printenv\s*lang|lang=|locale)", 1, tolower(combined))
| project TimeGenerated, DeviceName, DeviceId, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessId, InitiatingProcessId, AccountName, SourceSystem, tool
| sort by TimeGenerated desc
| take 50

// Summary of detected tool(s)
| union (
    union isfuzzy=true DeviceProcessEvents, DeviceEvents, DeviceFileEvents
    | where DeviceId in (linuxDevices)
    | extend combined = strcat(
        tostring(ProcessCommandLine), " ",
        tostring(InitiatingProcessCommandLine), " ",
        tostring(FileName), " ",
        tostring(FolderPath), " ",
        tostring(FileOriginUrl), " ",
        tostring(RegistryValueData)
      )
    | where tolower(combined) matches regex @"\b(localectl|update-locale|printenv\s*lang|lang=|locale)\b"
    | extend tool = extract(@"(localectl|update-locale|printenv\s*lang|lang=|locale)", 1, tolower(combined))
    | summarize event_count = count() by tool
    | order by event_count desc
)
fail362.50s0.0143
gpt-5-mini-medium
systemd-localed
// Find processes that report/configure locale on Linux devices
// Note: do not hardcode a time filter here — the caller will set the time range
let linuxDeviceIds = DeviceInfo
| where tostring(OSPlatform) has "Linux"
| distinct DeviceId;
DeviceProcessEvents
| where DeviceId in (linuxDeviceIds)
// Look for known tool names or patterns indicating locale usage
| where (
    tolower(FileName) in ("locale","localectl","localed","hostnamectl")
    or tolower(ProcessCommandLine) has_any ("locale","localectl","localed","hostnamectl","lang=","lc_")
)
| extend ToolRaw = iff(isnotempty(FileName), FileName, tostring(split(trim(" ", ProcessCommandLine), " ")[0]))
| extend Tool = tolower(extract(@"([^/\\]+)$", 1, ToolRaw))
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Count=count(), SampleCmdlines=make_set(ProcessCommandLine, 5) by DeviceId, DeviceName, Tool
| order by LastSeen desc
| take 100
| project LastSeen, FirstSeen, Count, DeviceName, DeviceId, Tool, SampleCmdlines
fail232.95s0.0091
gpt-5-nano-high
locale
let linux_devices = DeviceInfo
| where OSPlatform contains 'Linux'
| project DeviceId;
DeviceProcessEvents
| where InitiatingProcessFileName in ('locale','localectl') or InitiatingProcessCommandLine has_any ('locale','localectl')
| join kind=inner (linux_devices) on DeviceId
| project TimeGenerated, DeviceName, ToolUsed = InitiatingProcessFileName, CommandLine = InitiatingProcessCommandLine, ProcessId = InitiatingProcessId
fail252.01s0.0037
gpt-5-nano-medium
locale
let LinuxDevices = DeviceInfo | where OSPlatform contains "Linux";
let LocaleProcs = DeviceProcessEvents
| where InitiatingProcessFileName in ("locale","localectl") or InitiatingProcessCommandLine contains "locale" or InitiatingProcessCommandLine contains "localectl"
| project TimeGenerated, DeviceName, DeviceId, ProcessId = InitiatingProcessId, ProcessFileName = InitiatingProcessFileName, ProcessCommandLine = InitiatingProcessCommandLine, InitiatingProcessFolderPath
| extend ToolUsed = iif(tolower(ProcessFileName) in ("locale","localectl"), ProcessFileName, iif(ProcessCommandLine contains "locale" or ProcessCommandLine contains "localectl", "locale", "Unknown"))
| distinct TimeGenerated, DeviceName, DeviceId, ProcessId, ProcessFileName, ProcessCommandLine, ToolUsed;
LocaleProcs
| join kind=inner (LinuxDevices) on DeviceId
| project TimeGenerated, DeviceName, DeviceId, ProcessId, ProcessFileName, ProcessCommandLine, ToolUsed
| sort by TimeGenerated desc
fail5191.10s0.0087
grok-3-beta
locale
DeviceProcessEvents
| join kind=inner DeviceInfo on DeviceId
| where OSPlatform == 'Linux'
| where ProcessCommandLine has 'locale' or InitiatingProcessFileName has 'locale' or ProcessCommandLine has 'localectl'
| project DeviceName, InitiatingProcessFileName, ProcessCommandLine, Timestamp
| order by Timestamp desc
fail126.54s0.0609
grok-3-mini-beta
locale
DeviceInfo
| where OSPlatform contains "Linux"
| project DeviceId, DeviceName
| join kind=inner (
    DeviceProcessEvents
    | where ProcessCommandLine contains "locale"
    | project DeviceId, ProcessCommandLine, FileName, TimeGenerated
) on DeviceId
| project DeviceName, ProcessCommandLine, FileName, TimeGenerated
| order by TimeGenerated desc
| summarize arg_max(TimeGenerated, *) by DeviceName, FileName
fail114.92s0.0021
o1-high
locale
DeviceProcessEvents
| where DeviceId in (DeviceInfo
    | where OSPlatform =~ "Linux"
    | distinct DeviceId)
| where ProcessCommandLine has_any("locale", "localectl") or FileName in~ ("locale", "localectl")
| project TimeGenerated, DeviceName, FileName, ProcessCommandLine, InitiatingProcessCommandLine
| order by TimeGenerated desc
fail190.24s0.6374
o1-low
locale
DeviceInfo
| where OSPlatform =~ "Linux"
| join kind=inner (
    DeviceProcessEvents
    | where ProcessCommandLine has_any ("locale", "localectl")
) on DeviceId
| project TimeGenerated, DeviceName, FileName, ProcessCommandLine, FolderPath
fail142.92s0.4811
o3-high
localectl
// --- Linux hosts only --------------------------------------------------
let linux_devices = DeviceInfo
| where OSPlatform =~ "Linux"
| distinct DeviceId;

// --- Processes that report locale settings -----------------------------
DeviceProcessEvents
| where DeviceId in (linux_devices)
// match either the binary name or its appearance in the full command line
| where FileName in~ ("localectl", "locale")
  or ProcessCommandLine has "localectl"
  or ProcessCommandLine has " locale "   // avoid matching LANG=, LC_*, etc.
| extend ToolUsed = case(
        FileName =~ "localectl" or ProcessCommandLine has "localectl", "localectl",
        FileName =~ "locale"     or ProcessCommandLine has " locale ",  "locale",
        "unknown")
| project TimeGenerated,
          DeviceName,
          DeviceId,
          ToolUsed,
          ProcessCommandLine,
          FolderPath,
          InitiatingProcessAccountName,
          InitiatingProcessFileName,
          InitiatingProcessCommandLine
| order by TimeGenerated desc
pass137.18s0.0262
o3-mini-high
locale
DeviceProcessEvents
| where tolower(InitiatingProcessCommandLine) contains "locale"
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine
| distinct DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine
fail111.36s0.0091
o3-mini-low
locale
DeviceProcessEvents
| where ProcessCommandLine has "locale"
| project TimeGenerated, DeviceName, FileName, ProcessCommandLine
| summarize EventCount = count() by FileName, ProcessCommandLine
| sort by EventCount desc
fail114.87s0.0105
o4-mini-high
locale
DeviceProcessEvents
| where ProcessCommandLine has "locale"
| join kind=inner (
    DeviceInfo
    | where OSPlatform has "Linux"
    | project DeviceId
) on DeviceId
| project TimeGenerated, DeviceName, FileName, ProcessId, ProcessCommandLine
fail126.76s0.0253
o4-mini-low
locale
// Search for executions of the 'locale' tool on Linux devices
let linuxDevices = DeviceInfo
    | where OSPlatform == "Linux"
    | distinct DeviceId;
DeviceProcessEvents
| where DeviceId in (linuxDevices)
| where FileName == "locale" or ProcessCommandLine startswith "locale"
| project TimeGenerated, DeviceName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by TimeGenerated desc
fail145.95s0.0110