Question Analysis

During a Linux investigation, you notice processes spawning curl and wget commands that pull a script from a remote GitHub raw URL and pipe it into bash. Identify the name of the script that was retrieved and executed.

d0c88567-803d-4dca-99b4-7ce65e7b257c
Question ID
6/23
Models Correct
1
Valid Answer
26%
Success Rate
Reference Answer

Human-validated correct answer for this question

echo-art-fish.sh
Model Performance Comparison

See how different AI models performed on this question

ModelAnswerKQL QueryStatusAttemptsTimeCost
gemini-2.5-flash-preview-04-17
No answer provided
No query generated
Incorrect
5
0.00s
0.0330
gpt-35-turbo
No answer provided
No query generated
Incorrect
5
0.00s
0.0114
gpt-4-turbo-2024-04-09
LinEnum.sh
DeviceProcessEvents | where ProcessCommandLine has_any('curl', 'wget') and ProcessCommandLine contains 'bash' | extend ScriptUrl = tostring(split(ProcessCommandLine, '|')[0]) | extend ScriptName = tostring(split(ScriptUrl, '/')[array_length(split(ScriptUrl, '/')) - 1]) | project DeviceName, FileName, ProcessCommandLine, ScriptUrl, ScriptName
Incorrect
1
14.74s
0.0732
gpt-4.1
No answer provided
No query generated
Incorrect
5
0.00s
0.0434
gpt-4.1-finetuned
No answer provided
No query generated
Incorrect
5
0.00s
0.0426
gpt-4.1-mini
pipe-to-shell.sh
DeviceProcessEvents | where ProcessCommandLine contains @"curl" or ProcessCommandLine contains @"wget" | where ProcessCommandLine contains @"raw.githubusercontent.com" | where ProcessCommandLine contains @"bash" or ProcessCommandLine contains @"| bash" | extend ScriptUrl = extract(@"https?://raw\.githubusercontent\.com[^\s|]+", 0, ProcessCommandLine) | extend ScriptName = extract(@"[^/]+$", 0, ScriptUrl) | project TimeGenerated, DeviceName, ProcessCommandLine, ScriptUrl, ScriptName | distinct ScriptName, DeviceName, TimeGenerated, ProcessCommandLine, ScriptUrl
Incorrect
1
20.65s
0.0029
gpt-4.1-nano
No answer provided
No query generated
Incorrect
5
0.00s
0.0017
gpt-4o
AutoSUID.sh
DeviceProcessEvents | where InitiatingProcessCommandLine contains "curl" or InitiatingProcessCommandLine contains "wget" | where InitiatingProcessCommandLine matches regex @"https:\/\/raw.githubusercontent.com\/.*\.sh" and InitiatingProcessCommandLine contains "bash" | extend ScriptName = extract(@"[\w-]+\.sh", 0, InitiatingProcessCommandLine) | project Timestamp, DeviceId, DeviceName, InitiatingProcessCommandLine, ScriptName
Incorrect
1
24.29s
0.0201
gpt-5-high
pipe-to-shell.sh
let linux_devices = DeviceInfo | where OSPlatform == "Linux" | project DeviceId; let gh_hosts = dynamic(["raw.githubusercontent.com","gist.githubusercontent.com","github.com"]); let pipe_indicators = dynamic(["| bash","|bash","| sh","|sh","bash -c","sh -c","bash <(","sh <("]); // Path A: Process events where the full pipeline is visible in the command line let process_hits = DeviceProcessEvents | where DeviceId in (linux_devices) | where ProcessCommandLine has_any ("curl","wget") | where ProcessCommandLine has_any (gh_hosts) | where ProcessCommandLine has_any (pipe_indicators) | extend Url = extract(@"https?://[^\s'""|)><]+", 0, ProcessCommandLine) | project TimeGenerated, DeviceId, DeviceName, AccountName, InitiatingProcessAccountName, FileName, ProcessCommandLine, Url; // Path B: Network events from curl/wget to GitHub raw hosts (captures URL even if pipeline not in process cmdline) let network_hits = DeviceNetworkEvents | where DeviceId in (linux_devices) | where InitiatingProcessFileName in ("curl","wget") | where RemoteUrl has_any (gh_hosts) | project TimeGenerated, DeviceId, DeviceName, AccountName=InitiatingProcessAccountName, InitiatingProcessAccountName, FileName=InitiatingProcessFileName, ProcessCommandLine=InitiatingProcessCommandLine, Url=RemoteUrl; union process_hits, network_hits | where isnotempty(Url) | extend ScriptName = tostring(extract(@"([^/?#]+)(?:\?[^#]*)?(?:#.*)?$", 1, Url)) | where isnotempty(ScriptName) | summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), DeviceCount=dcount(DeviceId), Devices=make_set(DeviceName), Examples=make_set(Url, 5) by ScriptName | order by LastSeen desc
Incorrect
1
181.17s
0.0818
gpt-5-mini-high
echo-art-fish.sh
// Identify scripts downloaded from GitHub raw URLs via curl/wget piped to bash let github_raw_patterns = dynamic(["raw.githubusercontent.com", "raw.githubusercontent.com", "raw.github.com","githubusercontent.com"]); let curl_wget_filter = (s:string) { s has "curl" and s has "|" and s has "bash" or s has "wget" and (s has "-O-" or s has "-qO-" or s has "-O -") and s has "|" and s has "bash" }; // Search DeviceProcessEvents (preferred) and DeviceEvents let procEvents = DeviceProcessEvents | where isnotempty(ProcessCommandLine) | where curl_wget_filter(ProcessCommandLine) or curl_wget_filter(InitiatingProcessCommandLine) | extend CmdLine = coalesce(ProcessCommandLine, InitiatingProcessCommandLine) | extend RemoteUrl = extract(@"((https?://)[^\s'\|]+raw[^\s'\|]+|https?://[^\s'\|]+raw\.githubusercontent\.com[^\s'\|]+|https?://[^\s'\|]*raw\.githubusercontent\.com[^\s'\|]+|https?://raw\.githubusercontent\.com[^\s'\|]+|https?://raw\.githubusercontent\.com[^\s'\|]+)", 1, CmdLine) | extend RemoteUrl = iff(isempty(RemoteUrl), extract(@"https?://[^\s'\|]+githubusercontent\.com[^\s'\|]+", 0, CmdLine), RemoteUrl) | extend ScriptName = trim_end(@"/", tostring(parse_url(RemoteUrl).Path)) | extend ScriptName = replace_regex(ScriptName, @"^.*/", "") | project TimeGenerated, DeviceName, ProcessId, ProcessCreationTime, FileName, CmdLine, RemoteUrl, ScriptName ; let devEvents = DeviceEvents | where isnotempty(ProcessCommandLine) or isnotempty(InitiatingProcessCommandLine) | where curl_wget_filter(ProcessCommandLine) or curl_wget_filter(InitiatingProcessCommandLine) | extend CmdLine = coalesce(ProcessCommandLine, InitiatingProcessCommandLine) | extend RemoteUrl = extract(@"https?://[^\s'\|]+(raw\.githubusercontent\.com|raw\.github\.com|rawgithubusercontent)\/[^\s'\|]+", 0, CmdLine) | extend RemoteUrl = iff(isempty(RemoteUrl), extract(@"https?://[^\s'\|]+githubusercontent\.com[^\s'\|]+", 0, CmdLine), RemoteUrl) | extend ScriptName = trim_end(@"/", tostring(parse_url(RemoteUrl).Path)) | extend ScriptName = replace_regex(ScriptName, @"^.*/", "") | project TimeGenerated, DeviceName, ProcessId=InitiatingProcessId, ProcessCreationTime=InitiatingProcessCreationTime, FileName=InitiatingProcessFileName, CmdLine, RemoteUrl, ScriptName ; // Combine and return distinct script names with sample evidence procEvents | union devEvents | where isnotempty(RemoteUrl) | summarize count(), Samples = make_list(pack_all(), 10) by ScriptName | order by count_ desc | project ScriptName, Count = count_, Samples
Correct
1
25.69s
0.0049
gpt-5-mini-low
No answer provided
No query generated
Incorrect
5
0.00s
0.0149
gpt-5-mini-medium
No answer provided
No query generated
Incorrect
5
0.00s
0.0155
gpt-5-nano-high
echo-art-fish.sh
DeviceProcessEvents | where InitiatingProcessCommandLine contains "curl" or InitiatingProcessCommandLine contains "wget" | where InitiatingProcessCommandLine contains "raw.githubusercontent.com" or InitiatingProcessCommandLine contains "githubusercontent.com" | where InitiatingProcessCommandLine contains "| bash" or InitiatingProcessCommandLine contains "| /bin/bash" or InitiatingProcessCommandLine contains "| /bin/sh" | extend ScriptUrl = extract("https?://[^ ]+", 0, InitiatingProcessCommandLine) | extend ScriptName = extract("https?://[^/]+/.*/([^/?#]+)(?:[?#].*)?$", 1, ScriptUrl) | where isnotempty(ScriptName) | summarize FirstSeen = min(TimeGenerated), DeviceCount = dcount(DeviceId), Hits = count() by ScriptName, ScriptUrl | order by Hits desc
Correct
2
62.30s
0.0042
gpt-5-nano-medium
No answer provided
No query generated
Incorrect
5
0.00s
0.0093
grok-3-beta
echo-art-fish.sh
DeviceProcessEvents | where ProcessCommandLine contains 'curl' or ProcessCommandLine contains 'wget' | where ProcessCommandLine contains 'github' | where ProcessCommandLine contains '| bash' | extend ScriptName = extract('.*\\/([^\\/\\?\\s]+)', 1, ProcessCommandLine) | project Timestamp, DeviceName, ProcessCommandLine, ScriptName | order by Timestamp desc
Correct
5
39.67s
0.0947
grok-3-mini-beta
pipe-to-shell.sh
DeviceProcessEvents | where ProcessCommandLine matches regex @'\bcurl\b.*\|\b.*\bbash\b' or ProcessCommandLine matches regex @'\bwget\b.*\|\b.*\bbash\b' | extend FullURL = extract(@'(https?://[^\s|]+)', 1, ProcessCommandLine) | extend arr = split(FullURL, '/') | extend ScriptName = arr[array_length(arr) - 1] | project TimeGenerated, DeviceName, ProcessCommandLine, ScriptName | summarize ScriptNames = make_set(ScriptName) by DeviceName
Incorrect
3
36.57s
0.0045
o1-high
LinEnum.sh
DeviceProcessEvents | where ActionType == "ProcessCreated" | where ProcessCommandLine has_any ("curl", "wget") | where ProcessCommandLine has "raw.githubusercontent.com" and ProcessCommandLine has "bash" | extend DownloadedUrl = extract(@"(https?:\/\/[^\s|]+)", 0, ProcessCommandLine) | extend ScriptName = extract(@"\/([^\/\?]+)(\?.*)?$", 1, DownloadedUrl) | project TimeGenerated, DeviceId, DeviceName, AccountName, ProcessCommandLine, DownloadedUrl, ScriptName | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by DeviceId, DeviceName, AccountName, ScriptName | order by EndTime desc
Incorrect
2
115.36s
0.6308
o1-low
echo-art-fish.sh
DeviceProcessEvents | where ActionType == "ProcessCreated" | where tolower(InitiatingProcessCommandLine) has_any ("curl", "wget") and tolower(InitiatingProcessCommandLine) has "raw.githubusercontent.com" and tolower(InitiatingProcessCommandLine) has "| bash" | extend ScriptName = extract(@"raw\.githubusercontent\.com[^ ]+/(?<script>[^ ]+)", 1, tolower(InitiatingProcessCommandLine)) | project Timestamp, DeviceName, InitiatingProcessCommandLine, ScriptName | order by Timestamp desc
Correct
3
61.01s
0.5518
o3-high
LinEnum.sh
// ------------------------------------------------------------------------------------------------ // Detect scripts fetched from GitHub raw via curl / wget and immediately executed through a pipe // (e.g. curl https://raw.githubusercontent.com/user/repo/script.sh | bash ) // ------------------------------------------------------------------------------------------------ // Time range will be added automatically by the hunting portal, so no explicit where TimeGenerated // clause is required here. let pipeIndicators = dynamic(["|bash","| bash","|sh","| sh","bash -","sh -"]); DeviceProcessEvents // 1. Focus on the typical downloader utilities and the shell that is used to execute the script | where FileName in~ ("bash","sh","curl","wget") // 2. Command-line must reference GitHub raw content and contain a pipe that forwards the content to a shell | where ProcessCommandLine has "raw.githubusercontent.com" and ProcessCommandLine has_any(pipeIndicators) // 3. Pull the full raw URL out of the command line (greedy until we hit whitespace or the pipe symbol) | extend RawUrl = extract(@"((?:http|https)://[^\s'""|<>]+)", 1, ProcessCommandLine) | where isnotempty(RawUrl) // 4. Derive just the script name (the last element after the final '/') | extend ScriptName = extract(@"([^/]+)$", 1, RawUrl) // 5. Return the interesting columns; hunting portal will add the time filter | project TimeGenerated, DeviceName, AccountName, Executable = FileName, ProcessCommandLine, RawUrl, ScriptName | order by TimeGenerated desc
Incorrect
2
73.57s
0.0418
o3-mini-high
echo-art-fish.sh
DeviceProcessEvents | where ProcessCommandLine has_any ("curl", "wget") | where ProcessCommandLine contains "raw.githubusercontent.com" | where ProcessCommandLine contains "| bash" | extend ScriptName = extract(@"https?://raw\.githubusercontent\.com/[^/]+/[^/]+/[^/]+/([^ \|]+)", 1, ProcessCommandLine) | where isnotempty(ScriptName) | summarize Occurrences = count() by ScriptName, ProcessCommandLine | order by Occurrences desc
Correct
1
13.12s
0.0088
o3-mini-low
LinEnum.sh
DeviceProcessEvents | where ProcessCommandLine has_any ("curl", "wget") | where ProcessCommandLine contains "raw.githubusercontent.com" | where ProcessCommandLine contains "bash" | extend ScriptName = extract(@"raw\.githubusercontent\.com/\S+/([^/]+\.sh)", 1, ProcessCommandLine) | where isnotempty(ScriptName) | distinct ScriptName
Incorrect
1
61.96s
0.0116
o4-mini-high
echo-art-fish.sh
DeviceProcessEvents | where TimeGenerated between (startofday(ago(7d)) .. now()) // timerange will be set by the external control | where ProcessCommandLine has_any ("curl", "wget") | where ProcessCommandLine contains "raw.githubusercontent.com" | where ProcessCommandLine contains "bash" or ProcessCommandLine contains "|" // Extract the raw.githubusercontent.com URL | extend DownloadUrl = extract(@"(https?://raw\.githubusercontent\.com/[^\s|]+)", 1, ProcessCommandLine) | where isnotempty(DownloadUrl) // Parse out the script name (last segment of the URL) | extend ScriptName = tostring(split(DownloadUrl, "/")[array_length(split(DownloadUrl, "/")) - 1]) | project TimeGenerated, DeviceName, InitiatingProcessFileName, ProcessCommandLine, DownloadUrl, ScriptName | sort by TimeGenerated desc
Correct
1
30.30s
0.0134
o4-mini-low
pipe-to-shell.sh
DeviceProcessEvents | where ActionType == "ProcessCreated" // Only look for curl or wget invocations | where ProcessCommandLine contains "curl" or ProcessCommandLine contains "wget" // Focus on raw GitHub URLs | where ProcessCommandLine contains "raw.githubusercontent.com" // Extract the full URL being fetched | extend DownloadUrl = extract(@"(https?://raw\.githubusercontent\.com/[^\s'""\|]+)", 1, ProcessCommandLine) | where isnotempty(DownloadUrl) // Derive the script name from the URL by taking the last path segment | extend ScriptName = tostring(split(DownloadUrl, "/")[-1]) // Filter for typical shell script extensions | where ScriptName endswith ".sh" or ScriptName endswith ".bash" // Summarize by script name to see which scripts were pulled and executed | summarize Count = count() by ScriptName | sort by Count desc
Incorrect
4
108.17s
0.0301