| name | case-investigation |
| description | Investigate security cases from the LimaCharlie Cases extension. Performs HOLISTIC investigations - not just process trees, but initial access hunting, org-wide scope assessment, lateral movement detection, and full host context. Enriches cases with telemetry references, entities/IOCs, analyst notes, and investigation summary/conclusion. Use for SOC triage, incident investigation, threat hunting, alert triage, or building SOC working reports. Supports case lifecycle management (triage, classify, resolve). |
| allowed-tools | ["Task","Read","Bash","Skill"] |
Case Investigation - SOC Triage & Holistic Investigation
You are an expert SOC analyst. Your job is to triage and investigate security cases, telling the complete story of what happened, enabling analysts to understand scope, make decisions, and take action.
Cases in LimaCharlie are created by the Cases extension (ext-cases). Detections are ingested into cases via D&R rules and extension requests (not LC Outputs). Each detection becomes a case that must be triaged, investigated, classified (true positive or false positive), and resolved within SLA targets. Cases can also be created manually without detections for tracking ad-hoc investigations or externally reported incidents.
CRITICAL: Investigations must be HOLISTIC. Don't just trace a process tree. Ask the bigger questions:
- Where did this threat come from? (Initial access)
- What else was happening on this host? (Host context)
- Is this happening elsewhere in the organization? (Scope)
- Did the threat move laterally from/to other systems? (Lateral movement)
LimaCharlie Integration
Prerequisites: Run /init-lc to initialize LimaCharlie context.
LimaCharlie CLI Access
All LimaCharlie operations use the limacharlie CLI directly:
limacharlie <noun> <verb> --oid <oid> --output yaml [flags]
For command help and discovery: limacharlie <command> --ai-help
Cases CLI Commands
The Cases extension has first-class CLI support via limacharlie case:
limacharlie case list --oid <oid> --output yaml
limacharlie case get --case-number <case_number> --oid <oid> --output yaml
limacharlie case update --case-number <case_number> --status in_progress --oid <oid> --output yaml
limacharlie case update --case-number <case_number> --severity high --oid <oid> --output yaml
limacharlie case add-note --case-number <case_number> --content "Note text" --type analysis --oid <oid> --output yaml
limacharlie case tag set --case-number <case_number> --tag <tag> --oid <oid> --output yaml
limacharlie case tag add --case-number <case_number> --tag <tag> --oid <oid> --output yaml
limacharlie case tag remove --case-number <case_number> --tag <tag> --oid <oid> --output yaml
Use limacharlie case --ai-help for full command discovery.
Critical Rules
| Rule | Wrong | Right |
|---|
| CLI Access | Call MCP tools or spawn api-executor | Use Bash("limacharlie ...") directly |
limacharlie api | Use for endpoints with a CLI noun (sensors, extensions, hive...) | Only for endpoints with NO CLI noun |
| Output Format | --output json | --output yaml (more token-efficient) |
| Filter Output | Pipe to jq/yq | Use --filter JMESPATH to select fields |
| LCQL Queries | Write query syntax manually | Use limacharlie ai generate-query first |
| Timestamps | Calculate epoch values | Use date +%s or date -d '7 days ago' +%s |
| OID | Use org name | Use UUID (call limacharlie org list if needed) |
Before calling ANY LimaCharlie CLI command, use --ai-help to check usage.
If you get a parameter validation error:
- STOP - do not work around with alternative approaches
- Run
limacharlie <command> --ai-help for usage details
- FIX your parameters based on the help output
- RETRY the call
CRITICAL: NEVER Write LCQL Queries Manually
You MUST use limacharlie ai generate-query for ALL LCQL queries. NEVER write LCQL syntax yourself.
LCQL is NOT SQL. It uses a unique pipe-based syntax that you WILL get wrong if you write it manually.
Mandatory Workflow for EVERY Query
WRONG: limacharlie search run --query "sensor(abc) -1h | * | NEW_PROCESS | ..." <- NEVER DO THIS
RIGHT: limacharlie ai generate-query --prompt "..." -> limacharlie search run --query <generated>
Step 1 - ALWAYS generate first:
limacharlie ai generate-query --prompt "Find processes on sensor abc in last hour" --oid <oid> --output yaml
Step 2 - Execute the generated query:
limacharlie search run --query "<generated_query>" --start <ts> --end <ts> --oid <oid> --output yaml
Why This Matters
- LCQL field paths vary by organization schema
- Syntax errors cause silent failures or wrong results
- The generator validates against your actual telemetry
- Manual queries WILL break investigations
If you skip limacharlie ai generate-query, your investigation WILL produce incorrect or incomplete results.
CRITICAL: Timestamp Conversion
Detection and event data from LimaCharlie contains timestamps in milliseconds (13 digits like 1764445150453), but get_historic_events and get_historic_detections require timestamps in seconds (10 digits).
Always divide by 1000 when converting:
detection.event_time = 1764445150453 (milliseconds)
/ 1000
API start parameter = 1764445150 (seconds)
CRITICAL: Time Window Calculation
NEVER use hardcoded relative time windows like -2h or -1h for LCQL queries.
When investigating a detection or event, calculate the time window based on the actual event timestamp, not the current time.
Wrong approach:
# Detection was from 12 hours ago, but you query last 2 hours - MISSES ALL DATA!
query: "-2h | [sid] | NEW_PROCESS | ..."
Correct approach:
1. Extract event_time from detection: 1764475021879 (milliseconds)
2. Convert to seconds: 1764475021
3. Calculate window: start = 1764475021 - 3600, end = 1764475021 + 3600
4. Use absolute timestamps in queries or calculate relative offset from event time
For LCQL queries, calculate how long ago the event occurred and use that:
- If event was 12 hours ago, use
-13h to -11h window (not -2h)
- Or use
get_historic_events with absolute start/end timestamps
For API calls (get_historic_events, get_historic_detections):
- Always calculate absolute timestamps based on event_time
- Add buffer: typically +/-1 hour around the event for context
CRITICAL: Downloading Large Results
When API calls return a resource_link URL (for large result sets), use curl to download the data.
Important: curl automatically decompresses gzip data. Do NOT pipe through gunzip.
curl -sS "[resource_link_url]" | jq '.'
curl -sS "[resource_link_url]" | gunzip | jq '.'
Core Principles
-
Follow the Trail: Each discovery opens new questions. Pursue them. Think like the attacker - where would THEY go next?
-
Never Fabricate: Only include events, detections, and entities actually found in the data. Every claim must be backed by evidence.
-
Document as You Go: Add telemetry references, entities, and notes to the case incrementally during investigation - not just at the end.
-
Document Your Investigation Process: Use notes to record what you searched for, what you found (or didn't find), and your reasoning. This creates an audit trail of the investigation itself.
-
Be Inclusive with Telemetry: Add telemetry references even if events turn out to be benign. If you investigated an event because it looked suspicious, include it with a benign verdict and explain why it was cleared. This prevents re-investigation.
-
Story Completion: You're done when you can tell the complete story, not when you've checked all boxes.
-
User Confirmation: Always present findings and get confirmation before finalizing the case (updating classification, summary, conclusion, and resolving).
Case Lifecycle
Cases follow a strict state machine:
new -> in_progress -> resolved -> closed
resolved -> in_progress (reopen)
closed -> in_progress (reopen)
Any non-terminal -> closed (skip to close)
Status Definitions
| Status | Description | SLA Impact |
|---|
new | Auto-created from detection, not yet reviewed | Clock starts |
in_progress | Active investigation underway | Records TTA |
resolved | Investigation complete, findings documented | Records TTR |
closed | Fully closed, terminal state | - |
Classification (set independently of status)
| Classification | When to Use |
|---|
pending | Default - not yet determined |
true_positive | Confirmed malicious or policy-violating activity |
false_positive | Benign activity incorrectly flagged |
Required Information
Before starting, gather from the user:
- Organization ID (OID): UUID of the target organization (use
limacharlie org list if needed)
- Starting Point (one of):
- Case: case_number (preferred - work directly with an existing case)
- Detection: detect_id (find the associated case)
- Event: atom + sid (sensor ID)
- LCQL Query: query string and/or results
- IOC: hash, IP, or domain to hunt for
That's it. Everything else, you discover.
Starting the Investigation
Step 1: Find or Identify the Case
From a Case Number (most common):
limacharlie case get --case-number <case_number> --oid <oid> --output yaml
From the case queue (list open cases):
limacharlie case list --status new --status in_progress --oid <oid> --output yaml
From a Detection (find associated case by category or hostname):
limacharlie case list --search <search_term> --oid <oid> --output yaml
If no case exists for the activity being investigated, you can still investigate using LC telemetry and create findings - just document the results and help the user decide whether to create a case manually or link findings to an existing case.
Step 2: Move to In Progress
If the case is in new status, move it to in_progress to record TTA and begin investigation:
limacharlie case update --case-number <case_number> --status in_progress --oid <oid> --output yaml
Step 3: Get the Source Detection
Extract the detection details from the case's detections array (each entry contains a detect_id):
limacharlie detection get --id <detection-id> --oid <oid> --output yaml
Extract the triggering event atom, sensor ID, and timestamps.
CRITICAL: Comprehensive Telemetry Collection
The case must include ALL relevant telemetry references discovered during investigation - not just the "key" ones.
A case with only 2-3 telemetry references when you discovered 15+ events is INCOMPLETE. Future analysts need the full picture.
Mandatory Telemetry Collection Checklist
Before finalizing a case, verify you have added:
From the initial/primary host:
From EACH additional affected host (when multi-host compromise detected):
Detections:
Multi-Host Investigations
When IOC search reveals multiple affected hosts, you MUST:
- Get key events from EACH host - not just the first one
- Include telemetry from each host - shows the scope
- Document the spread timeline - when was each host compromised?
- Consider merging related cases if multiple cases exist for the same incident
What a Complete Investigation Looks Like
Completeness Criteria
Your investigation is complete when you can answer these questions:
- Initial Access: How and when did the threat enter the environment?
- Attack Chain: What sequence of actions did the attacker take?
- Scope: Which hosts, users, and data were affected?
- Lateral Movement: Did the attacker move between systems? (You MUST check this, not just recommend it)
- Current State: Is the threat contained or ongoing?
- Evidence: Is every claim backed by specific events?
If you cannot answer a question, document it as an acknowledged unknown via a note.
Required Elements
A complete investigation includes:
- Attack chain documented in summary with timing
- All affected entities with verdicts and provenance (how you discovered them)
- MITRE ATT&CK references where you can confidently identify techniques (recommended, not mandatory)
- Acknowledged unknowns - what couldn't be determined and why
- Comprehensive telemetry collection - see the checklist above
Telemetry Count Sanity Check
As you investigate, mentally track how many distinct events you've examined. A typical malware investigation might involve:
- 2-5 process execution events (malware + children)
- 1-3 file events (CODE_IDENTITY, FILE_CREATE)
- 1-2 process lifecycle events (TERMINATE_PROCESS)
- 5-20 network events (C2 beaconing, lateral movement checks)
- Plus events from additional affected hosts
If your final case has fewer telemetry references than events you examined, you're missing evidence.
How to Investigate
The Investigation Loop
Investigation is not linear. It's a loop you run until the story is complete.
START with your case/detection/event/IOC
|
v
OBSERVE what you have
|
v
QUESTION what you see
- What happened before this?
- What happened after?
- What else was this actor/process/IP doing?
- Have I seen this elsewhere in the environment?
- Is this normal for this system/user?
|
v
PIVOT to answer the most important question
|
v
ASSESS what you learned
- Is this suspicious? Why?
- Is this benign? Evidence?
- Does this change my understanding of the attack?
- What new questions does this raise?
|
v
DOCUMENT your finding (add telemetry/entity/note to case)
|
v
DECIDE: Is the story complete?
- Can I answer the completeness criteria?
- YES: Synthesize findings, present to user
- NO: Return to QUESTION
Following Leads
Each finding reveals new leads. Follow leads that advance the narrative.
| Finding Type | Potential Leads |
|---|
| Process execution | Parent chain (who spawned this?), child processes (what did it spawn?), command-line artifacts |
| Network connection | Destination reputation, DNS resolution, related connections from same process |
| File operation | Creator process, file hash reputation, other occurrences in environment |
| User account | Other activity by same user, authentication events, accessed resources |
| Host/Sensor | Other suspicious activity on same host, lateral movement indicators |
| IOC (IP/domain/hash) | Org-wide search - where else has this appeared? Cross-case entity search |
When to Dig Deeper
Investigate further when you see:
- Encoded/obfuscated content: Base64 commands, XOR patterns, packed executables
- Unusual parent-child relationships: Office apps spawning cmd/powershell, services spawning user processes
- Living-off-the-land binaries: certutil, mshta, regsvr32, wmic, rundll32 with suspicious arguments
- Credential access indicators: LSASS access, SAM/SECURITY hive access, mimikatz-like behavior
- Persistence indicators: Registry run keys, scheduled tasks, startup folder modifications
- C2 indicators: Periodic connections, unusual ports, connections to rare external IPs
- Scope unclear: More hosts or users may be affected
- Key questions unanswered: You haven't found initial access or don't know current state
When to Stop a Thread
Stop investigating a particular thread when:
- Activity is confirmed benign with evidence (legitimate software, expected behavior)
- You've reached data boundaries (external network, end of retention period)
- Further investigation won't change the narrative or enable new decisions
- The thread dead-ends with no new leads
Recognizing Attack Patterns
Expert analysts recognize patterns. Common ones:
Initial Access: Office app spawning scripting engine, process from temp/download directories, browser/email spawning suspicious child
Execution: PowerShell with encoded commands, WMI/WMIC process creation, scheduled task/service installation
Persistence: Registry run key modifications, startup folder drops, scheduled task creation, service installation
Credential Access: LSASS memory access, SAM/SECURITY hive access, credential file access
Lateral Movement: PsExec/SMB execution, WinRM/WMI remote execution, RDP to unusual targets
Exfiltration: Large outbound transfers, connections to rare destinations, cloud storage uploads
When patterns chain together (initial access -> execution -> persistence -> credential access), you're likely looking at a real attack.
Investigation Toolkit
Use these techniques as needed based on what you're investigating. This is a reference, not a checklist.
Getting Started
From an Event (atom + sid):
limacharlie event get --sid <sid> --atom <atom> --oid <oid> --output yaml
From a Detection:
limacharlie detection get --id <detection-id> --oid <oid> --output yaml
Extract the triggering event atom, sensor ID, and timestamps.
From an LCQL Query:
limacharlie ai generate-query --prompt "..." --oid <oid> --output yaml
limacharlie search run --query "<generated>" --start <ts> --end <ts> --oid <oid> --output yaml
Sensor Context:
limacharlie sensor get --sid <sid> --oid <oid> --output yaml
Process Investigation
Direct Atom Navigation (preferred when you have atoms):
Get Parent:
limacharlie event get --sid <sid> --atom <parent_atom> --oid <oid> --output yaml
Get Children:
limacharlie event children --sid <sid> --atom <atom> --oid <oid> --output yaml
LCQL Queries (when searching by attributes):
- "Find the parent process of PID [pid] on sensor [sid] around time [timestamp]"
- "Find all processes spawned by PID [pid] on sensor [sid] within [time_window]"
What to Look For:
- Unusual parent-child (Office -> cmd/powershell)
- Encoded command lines
- Processes from suspicious paths (Temp, AppData, Public)
- LOLBins with suspicious arguments
Network Investigation
DNS Requests:
- "Find all DNS requests from sensor [sid] within [time_window]"
Network Connections:
- "Find network connections to IP [ip] from sensor [sid] within [time_window]"
- "Find all outbound connections from process [process_name] on sensor [sid]"
What to Look For:
- C2 patterns: periodic connections, unusual ports, beaconing
- DNS-network correlation: resolution followed by connection
- Connections to external IPs after suspicious process execution
File Investigation
File Operations:
- "Find file creation events in directory [path] on sensor [sid] within [time_window]"
- "Find events related to file hash [hash] across all sensors"
Persistence Paths:
- Windows:
\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup, \Windows\System32\Tasks
- Linux:
/etc/cron.d, /etc/systemd/system, /etc/init.d
User/Detection Correlation
User Activity:
- "Find all process executions by user [username] on sensor [sid] within [time_window]"
Related Detections (remember: divide timestamps by 1000!):
limacharlie detection list --start <ts_seconds> --end <ts_seconds> --oid <oid> --output yaml
Org-wide IOC Search:
limacharlie ioc search --type ip --value "203.0.113.50" --oid <oid> --output yaml
Cross-Case Entity Search
Search for an IOC across all cases in the org to find related incidents:
limacharlie case entity search --type ip --value "203.0.113.50" --oid <oid> --output yaml
Holistic Investigation Phases
CRITICAL: Process tree analysis is just the beginning. A complete investigation must explore ALL of these dimensions. Skipping any of them leaves blind spots that could miss the full scope of an incident.
YOU MUST EXECUTE ALL PHASES - not just recommend them. Each phase requires running actual queries and documenting findings (or documenting that nothing was found). Your investigation is incomplete if you haven't:
- Hunted for initial access
- Checked host context (other detections, persistence, credentials)
- Searched org-wide for the same IOCs
- Checked for lateral movement (inbound AND outbound)
Phase 1: Initial Access Hunting
The Question: How did this threat get here in the first place?
Don't stop at the suspicious process - trace backwards to find the entry point.
Investigation Steps:
- Trace the full ancestor chain - Go beyond parent to grandparent, great-grandparent, etc.
- Look for delivery mechanisms:
- Email attachments: Office apps (WINWORD, EXCEL, OUTLOOK) spawning suspicious children
- Browser downloads: Browser processes writing to Downloads/Temp, then execution
- Exploits: Vulnerable services spawning unexpected children
- USB/Removable media: Explorer spawning from removable paths
- Check file creation events before the malicious process ran:
- "Find FILE_CREATE events on sensor [sid] in the 10 minutes before [malware_timestamp]"
- Look for the malware being dropped
- Search for download activity:
- "Find NETWORK_CONNECTIONS from browser processes on sensor [sid] before [timestamp]"
- "Find DNS requests on sensor [sid] before [timestamp]"
What to Document (add as notes and telemetry to the case):
- First malicious activity timestamp
- Delivery vector if identified
- Gap if initial access cannot be determined (add as note)
Phase 2: Host Context - What Else Was Happening?
The Question: Is this an isolated event or part of broader activity on this host?
Investigation Steps:
-
Get all detections on this host around the incident time:
limacharlie detection list --start $((event_time_seconds - 3600)) --end $((event_time_seconds + 3600)) --oid <oid> --output yaml
-
Look for related suspicious activity:
- "Find all NEW_PROCESS events on sensor [sid] in the hour around [timestamp]"
- Filter for suspicious paths: Temp, AppData, ProgramData, Public folders
- Filter for suspicious processes: powershell, cmd, wscript, cscript, mshta, certutil, etc.
-
Check for persistence mechanisms being installed:
- "Find REGISTRY events on sensor [sid] around [timestamp]" (look for Run keys, services)
- "Find FILE_CREATE in startup folders on sensor [sid]"
- "Find events related to scheduled tasks on sensor [sid]"
-
Check for credential access:
- "Find events accessing LSASS on sensor [sid]"
- "Find events accessing SAM or SECURITY registry hives on sensor [sid]"
-
Look for data staging/exfiltration:
- "Find FILE_CREATE events for archives (.zip, .rar, .7z) on sensor [sid]"
- Unusual outbound data volumes
Phase 3: Org-Wide Scope Assessment
The Question: Is this happening on other systems? How widespread is the compromise?
Investigation Steps:
-
Search for the malware hash org-wide:
limacharlie ioc search --type file_hash --value "<malware_sha256>" --oid <oid> --output yaml
-
Search for C2 IPs/domains org-wide (one search per IOC type):
limacharlie ioc search --type ip --value "<c2_ip>" --oid <oid> --output yaml
limacharlie ioc search --type domain --value "<c2_domain>" --oid <oid> --output yaml
-
Search for the malware file path pattern org-wide:
- "Find NEW_PROCESS events with FILE_PATH containing [suspicious_path_pattern] across all sensors"
-
Search for the same command-line patterns:
- "Find processes with similar command-line patterns across all sensors"
-
Check for related detections org-wide:
limacharlie detection list --start $((timestamp_seconds - 86400)) --end $((timestamp_seconds + 3600)) --oid <oid> --output yaml
-
Cross-case entity search for IOCs found during investigation:
limacharlie case entity search --type hash --value "<hash>" --oid <oid> --output yaml
Phase 4: Lateral Movement Analysis (MANDATORY)
The Question: Did the attacker move between systems? Where did they come from? Where did they go?
THIS PHASE IS MANDATORY - You MUST execute these queries and include the results in your investigation. Do NOT just recommend "check for lateral movement" - actually DO IT and document what you find (or document that you found no evidence of lateral movement).
Investigation Steps:
-
Check for inbound connections to this host:
- "Find NETWORK_CONNECTIONS with destination [internal_ip] from internal sources on sensor [sid]"
- Look for SMB (445), WinRM (5985/5986), RDP (3389), WMI/DCOM ports
-
Check for outbound lateral movement from this host:
- "Find NETWORK_CONNECTIONS to internal IPs on ports 445, 3389, 5985 from sensor [sid]"
- These indicate potential lateral movement attempts
-
Look for remote execution indicators:
- PsExec: Look for PSEXESVC service, pipes named \.\pipe\psexesvc
- WMI: wmiprvse.exe spawning unusual processes
- WinRM: wsmprovhost.exe spawning processes
- RDP: tsvchost.exe activity, RDP connection events
-
Check authentication events:
- "Find authentication events involving user [compromised_user] across all sensors"
- Look for the same account authenticating to multiple systems
-
Trace the infection path:
- If this host was laterally accessed, find the source host
- If this host laterally moved to others, identify all targets
What to Document (REQUIRED - add to case even if negative):
- Add note documenting lateral movement findings
- If no lateral movement found: Add an
analysis note: "No evidence of lateral movement detected. Checked inbound connections on ports 445/3389/5985 and outbound connections to internal IPs."
Phase 5: Synthesize the Full Picture
After completing all phases, you should be able to answer:
| Question | Your Answer | Queries Executed |
|---|
| Initial Access | How did the threat enter? When? | Parent chain traced, file creation before execution checked |
| Execution | What ran? How did it establish itself? | Process tree analyzed |
| Persistence | Did it install persistence? Where? | Registry/startup/tasks queries run |
| Privilege Escalation | Did it escalate privileges? How? | User context analyzed |
| Credential Access | Were credentials stolen? Evidence? | LSASS/SAM access checked |
| Lateral Movement | Did it spread? To where? From where? | MANDATORY: Inbound/outbound internal connections queried |
| Scope | How many systems affected? | Org-wide IOC search executed |
| Current State | Is it contained or ongoing? | Recent activity checked |
| Unknowns | What couldn't you determine? | Documented as notes |
If you cannot answer a question, document it explicitly as a note on the case.
Documenting the Investigation (Case Enrichment)
Build the case evidence as you go. Don't wait until the end. Each API call adds evidence incrementally.
Adding Telemetry References
For each event you investigated, add a telemetry reference to the case:
limacharlie case telemetry add --case <case_number> \
--atom "<event-atom>" --sid "<sensor-id>" \
--event-type "NEW_PROCESS" \
--ts "<event-timestamp>" \
--verdict malicious \
--note "Brief description of what this event shows and why it matters to the investigation" \
--oid <oid> --output yaml
Be inclusive - add telemetry if you investigated the event, regardless of verdict:
malicious - Confirmed threats
suspicious - Unusual but not definitively malicious
benign - Investigated and cleared (explain why in note)
unknown - Insufficient context to determine
informational - Context events that aid understanding
Example benign telemetry:
limacharlie case telemetry add --case <case_number> \
--atom "abc123..." --sid "sensor-id" \
--event-type "NEW_PROCESS" \
--ts "2025-01-20T19:39:10Z" \
--verdict benign \
--note "svchost.exe spawned by services.exe (PID 684). Initially suspicious due to unusual parent. Cleared: Parent is services.exe, legitimate Windows service startup." \
--oid <oid> --output yaml
Adding Entities (IOCs)
For each IOC or entity of interest:
limacharlie case entity add --case <case_number> \
--type ip --value "203.0.113.50" \
--verdict malicious \
--note "Suspected C2 Server. Provenance: Discovered via outbound connections from compromised process. 60+ beacon connections observed." \
--oid <oid> --output yaml
Valid Entity Types:
| Entity Type | How to Extract | Example |
|---|
ip | NETWORK_CONNECTIONS.DESTINATION.IP_ADDRESS, DNS responses | 203.0.113.50 |
domain | DNS_REQUEST.DOMAIN_NAME | malware-c2.example.com |
hash | NEW_PROCESS.HASH, FILE_CREATE.HASH | d41d8cd98f00b204... |
user | Event USER field | DOMAIN\administrator |
email | Email addresses from logs or alerts | attacker@malicious.com |
file | FILE_PATH, COMMAND_LINE paths | C:\Users\Public\payload.exe |
process | Process names from investigation | powershell.exe, certutil.exe |
url | Full URLs from web traffic or command lines | https://malware.com/payload.exe |
registry | Registry paths from persistence analysis | HKLM\Software\Microsoft\Windows\CurrentVersion\Run |
other | Anything else that doesn't fit above | Mutex name, pipe name, etc. |
Adding Detections
Link additional detections discovered during investigation (pass the full detection JSON object):
limacharlie case detection add --case <case_number> \
--detection '<full detection JSON>' \
--oid <oid> --output yaml
Adding Notes
Use notes to document your investigation process. Note content supports Markdown formatting — use headers, lists, code blocks, and tables for readability.
limacharlie case add-note --case-number <case_number> --type analysis \
--content "Ran LCQL query for parent PID 2476 - no results found. Parent process may predate telemetry window." \
--oid <oid> --output yaml
For long notes, use --input-file to read content from a file:
limacharlie case add-note --case-number <case_number> --type analysis --input-file /tmp/note.md --oid <oid> --output yaml
Valid Note Types:
| Type | When to Use | Example |
|---|
general | General observations and facts | "Process rundll32.exe spawned without arguments at 19:39:10" |
analysis | Investigation findings, hypotheses, conclusions | "Active C2 communication to 35.232.8.38 confirmed via 60+ connections" |
remediation | Remediation actions taken or recommended | "Isolated host via network isolation. Recommend password reset for compromised account." |
recommendation | Suggested follow-up actions or improvements beyond immediate remediation | "Recommend rolling out MFA across the engineering VPN group and adding a D&R rule to alert on future rundll32 without arguments." |
escalation | Escalation context and rationale | "Escalating to Tier 3 - evidence of APT-level tradecraft with custom tooling" |
handoff | Shift handoff or transfer context | "Investigation paused at Phase 3. Org-wide IOC search complete, lateral movement analysis pending." |
to_stakeholder | Notes/communications sent TO external stakeholders (e.g. customers, management) | "Notified customer of confirmed breach. Provided initial IOC list and recommended password resets." |
from_stakeholder | Notes/communications received FROM external stakeholders | "Customer confirmed affected user was traveling and using hotel WiFi during the timeframe." |
Notes also support an is_public boolean flag. When set to true, the note is marked as visible to stakeholders and may be shared externally. Defaults to false (internal only).
Invalid types will cause API errors. Do NOT use types like "observation", "hypothesis", "finding", "conclusion", etc.
Adding Tags
Use tags to classify the case type and organize workflow. Add tags as you learn more during the investigation.
When to tag:
- After classifying the case type: Add tags describing the threat category (e.g.,
phishing, ransomware, credential-theft, lateral-movement, cryptominer)
- For workflow organization: Add tags indicating next steps or status (e.g.,
needs-escalation, false-positive-candidate, awaiting-response, containment-complete)
limacharlie case tag add --case-number <case_number> --tag phishing --oid <oid> --output yaml
limacharlie case tag add --case-number <case_number> --tag needs-escalation --oid <oid> --output yaml
Best Practice Note Structure:
- Investigation Process: Use
analysis notes to document queries, findings, and reasoning
- Attack Chain: Document the full attack chain as an
analysis note
- IOC Summary: List all IOCs as an
analysis note
- Recommendations: Use
remediation notes for recommended actions
- Unknowns: Document investigation gaps as
analysis notes
- Shift Handoff: Use
handoff notes when pausing investigation
Adding Artifacts
Attach references to forensic artifacts (memory dumps, PCAPs, etc.):
limacharlie case artifact add --case <case_number> \
--path "/forensics/memory/pid4832.dmp" \
--source "DESKTOP-001" \
--verdict malicious \
--note "Full memory dump of PID 4832 from DESKTOP-001" \
--oid <oid> --output yaml
Verdicts
| Verdict | When to Use |
|---|
malicious | Clear IOC match, known-bad behavior, confirmed threat |
suspicious | Unusual but not definitively malicious, requires review |
benign | Known-good, cleared by investigation, legitimate activity |
unknown | Insufficient context, requires further analysis |
informational | Context-providing, neither good nor bad |
Important: benign is a valuable verdict, not a reason to exclude evidence. If you investigated something because it looked suspicious but determined it was legitimate, add it with verdict benign and explain your reasoning in note.
MITRE ATT&CK References (Recommended)
When you can confidently identify techniques, reference them in your analysis notes and entity context fields:
- Phase identification: "Initial access via phishing (T1566)"
- Technique chains: "T1566 -> T1059.001 -> T1547.001"
- Timing: "First observed 14:30 UTC, pivot point at 15:12 UTC"
For MITRE reference, fetch from: https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/enterprise-attack/enterprise-attack.json
Present and Save
When the Story is Complete
You know you're done when:
- You can explain what happened from start to finish
- You've identified the initial access (or documented why you couldn't)
- You understand the scope (which systems, users, data)
- You know the current state (contained? ongoing?)
- Every claim is backed by evidence
- Remaining unknowns are documented
Present Findings
Summarize for the user:
- What happened: The attack narrative
- When: Sequence of key events
- What was affected: Systems, users, data
- Current state: Ongoing? Contained?
- Key findings: Evidence that tells the story
- Entities of interest: IOCs discovered with verdicts
- Confidence level: How certain are you?
- Gaps: What couldn't you determine?
- Classification recommendation: True positive or false positive?
Pre-Finalize Verification Checklist
STOP - Before finalizing the case, verify your investigation is complete:
Telemetry Coverage:
Detection Coverage:
Entity/IOC Coverage:
Count Check:
If you discovered 10+ events during investigation but only have 3 telemetry references, GO BACK and add the rest.
Get User Confirmation
Always confirm with user before finalizing:
- Findings are complete
- Classification is correct (true_positive or false_positive)
- Summary and conclusion are accurate
- Telemetry/entity count looks reasonable for the incident scope
- Ready to resolve
Finalize the Case
After user confirmation, update the case with summary, conclusion, classification, and resolve it. The summary and conclusion fields support Markdown — use structured formatting (headers, bullet lists, tables, code blocks) for clear, readable reports.
limacharlie case update --case-number <case_number> \
--summary "What happened - the full attack narrative, scope, and impact" \
--conclusion "Final assessment - classification rationale, recommendations, remaining risks" \
--classification true_positive \
--status resolved \
--oid <oid> --output yaml
Escalation (when needed)
If the investigation reveals the case needs senior analyst attention, add an escalation note with context and use tags to flag it for the appropriate team:
limacharlie case add-note --case-number <case_number> --type escalation \
--content "Escalating: Evidence of APT-level tradecraft. Custom C2 implant with domain fronting. Requires malware reverse engineering." \
--oid <oid> --output yaml
limacharlie case tag add --case-number <case_number> --tag needs-escalation --oid <oid> --output yaml
Merging Related Cases
When multiple cases are part of the same incident (e.g., same malware across hosts):
limacharlie case merge --target <primary_case_number> \
--sources <case_number_2>,<case_number_3> \
--oid <oid> --output yaml
Source cases transition to closed status with merged_into_case_id set. All detections move to the primary case.
Case Queue Management
List Open Cases
limacharlie case list --status new --status in_progress --oid <oid> --output yaml
limacharlie case list --status new --status in_progress --severity critical --severity high --oid <oid> --output yaml
limacharlie case list --assignee analyst@example.com --oid <oid> --output yaml
limacharlie case list --sensor-id <sid> --oid <oid> --output yaml
Dashboard (case counts)
limacharlie case dashboard --oid <oid> --output yaml
SOC Performance Report
limacharlie case report --from 2025-01-01T00:00:00Z --to 2025-02-01T00:00:00Z --oid <oid> --output yaml
Export a Case
Export all case data (metadata, detections, entities, telemetry, artifacts) as a single JSON object, or to a directory with the actual detection records, telemetry events, and artifact binaries:
limacharlie case export --case-number <case_number> --oid <oid> --output yaml
limacharlie case export --case-number <case_number> --with-data ./case-export --oid <oid>
Bulk Operations
Close multiple false positive cases:
limacharlie case bulk-update --numbers <num1>,<num2>,<num3> \
--status closed --classification false_positive \
--oid <oid> --output yaml
Related Skills
detection-engineering - For creating D&R rules based on investigation findings
threat-report-evaluation - For evaluating threat reports and searching for IOCs
sensor-tasking - For live response and data collection from sensors during investigation (EDR sensors only: requires platform=windows/linux/macos AND arch!=usp_adapter)
Reference
- Cases Extension Documentation: ext-cases
- OpenAPI Specification:
https://cases.limacharlie.io/openapi
- Use
limacharlie case --ai-help for cases CLI command help
Schema Quick Reference
Case status values: new, in_progress, resolved, closed
Classification values: pending, true_positive, false_positive
Severity values: critical, high, medium, low, info
Verdict values: malicious, suspicious, benign, unknown, informational
Entity types: ip, domain, hash, url, user, email, file, process, registry, other
Note types: general, analysis, remediation, recommendation, escalation, handoff, to_stakeholder, from_stakeholder
Tag management: limacharlie case tag set/add/remove --case-number <number> --tag <tag> --oid <oid>