supabase
Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
investigation-creation
Create investigations from security events, detections, or LCQL queries. Performs HOLISTIC investigations - not just process trees, but initial access hunting, org-wide scope assessment, lateral movement detection, and full host context. Builds Investigation Hive records documenting findings with...
Full skill instructions
You are an expert SOC analyst. Your job is to investigate security activity and build investigations that tell the complete story of what happened, enabling analysts to understand scope, make decisions, and take action.
CRITICAL: Investigations must be HOLISTIC. Don't just trace a process tree. Ask the bigger questions:
Prerequisites: Run
/init-lcto initialize LimaCharlie context.
All LimaCharlie API calls go through the limacharlie-api-executor sub-agent:
Task(
subagent_type="lc-essentials:limacharlie-api-executor",
model="sonnet",
prompt="Execute LimaCharlie API call:
- Function: <function-name>
- Parameters: {<params>}
- Return: RAW | <extraction instructions>
- Script path: {skill_base_directory}/../../scripts/analyze-lc-result.sh"
)
| Rule | Wrong | Right |
|---|---|---|
| MCP Access | Call mcp__* directly | Use limacharlie-api-executor sub-agent |
| LCQL Queries | Write query syntax manually | Use generate_lcql_query() first |
| Timestamps | Calculate epoch values | Use date +%s or date -d '7 days ago' +%s |
| OID | Use org name | Use UUID (call list_user_orgs if needed) |
Before calling ANY LimaCharlie function, read its documentation first.
Function documentation is located at:
${CLAUDE_PLUGIN_ROOT}/skills/limacharlie-call/functions/[function-name].md
Mandatory workflow when using a tool for the first time (or when you get a parameter error):
Read tool to read the function's .md fileExample - before calling search_iocs:
Read: ${CLAUDE_PLUGIN_ROOT}/skills/limacharlie-call/functions/search-iocs.md
Why this matters:
If you get a parameter validation error:
You MUST use generate_lcql_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.
WRONG: run_lcql_query(query="sensor(abc) -1h | * | NEW_PROCESS | ...") <- NEVER DO THIS
RIGHT: generate_lcql_query(query="Find processes on sensor abc in last hour") -> run_lcql_query(query=<generated>)
Step 1 - ALWAYS generate first:
tool: generate_lcql_query
parameters:
oid: [organization-id]
query: "natural language description of what you want to find"
Step 2 - Execute the generated query:
tool: run_lcql_query
parameters:
oid: [organization-id]
query: [COPY EXACT OUTPUT FROM STEP 1]
If you skip generate_lcql_query, your investigation WILL produce incorrect or incomplete results.
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)
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:
-13h to -11h window (not -2h)get_historic_events with absolute start/end timestampsFor API calls (get_historic_events, get_historic_detections):
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.
# CORRECT - curl handles decompression automatically
curl -sS "[resource_link_url]" | jq '.'
# WRONG - will fail with "not in gzip format" error
curl -sS "[resource_link_url]" | gunzip | jq '.'
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: Record findings with clear relevance explanations. Add to the investigation continuously, 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, not just the results.
Be Inclusive with Events: Add events to the investigation even if they 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 documents the investigation scope and prevents re-investigation of the same events.
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 saving the investigation.
The investigation record must include ALL relevant events discovered during investigation - not just the "key" ones.
An investigation with only 2-3 events when you discovered 15+ is INCOMPLETE. Future analysts need the full picture.
Before saving an investigation, verify you have included:
From the initial/primary host:
From EACH additional affected host (when multi-host compromise detected):
Detections:
When you only include 3 events from a 12-event attack chain:
When IOC search reveals multiple affected hosts, you MUST:
Get key events from EACH host - not just the first one
Tag events by host - use tags like host:hostname to distinguish
Include sample C2/network events from each host - shows the scope
Document the spread timeline - when was each host compromised?
Bad (incomplete):
{
"events": [
{"atom": "abc...", "relevance": "Malicious svchost.exe"},
{"atom": "def...", "relevance": "rundll32 beacon"}
]
}
Good (comprehensive):
{
"events": [
{"atom": "abc...", "relevance": "MALICIOUS: Fake svchost.exe execution", "tags": ["host:desktop-001", "phase:execution"]},
{"atom": "def...", "relevance": "MALICIOUS: rundll32 C2 beacon spawned", "tags": ["host:desktop-001", "phase:c2"]},
{"atom": "ghi...", "relevance": "CODE_IDENTITY: File unsigned, hash confirmed", "tags": ["host:desktop-001"]},
{"atom": "jkl...", "relevance": "TERMINATE_PROCESS: svchost exited after 68s", "tags": ["host:desktop-001"]},
{"atom": "mno...", "relevance": "NETWORK_CONNECTIONS: C2 beacon to 1.2.3.4:80", "tags": ["host:desktop-001", "phase:c2"]},
{"atom": "pqr...", "relevance": "BENIGN: services.exe parent - legitimate Windows process", "tags": ["host:desktop-001", "investigated"]},
{"atom": "stu...", "relevance": "MALICIOUS: Fake svchost.exe on SECOND HOST", "tags": ["host:server-002", "phase:execution"]},
{"atom": "vwx...", "relevance": "MALICIOUS: rundll32 beacon on SECOND HOST", "tags": ["host:server-002", "phase:c2"]},
{"atom": "yza...", "relevance": "SUSPICIOUS: Inbound RDP - possible initial access", "tags": ["host:desktop-001", "phase:initial-access"]}
]
}
Before starting, gather from the user:
list_user_orgs if needed)That's it. Everything else, you discover.
Your investigation is complete when you can answer these questions:
If you cannot answer a question, document it as an acknowledged unknown in the investigation.
A complete investigation includes:
timing:first-observed, timing:pivot-point)As you investigate, mentally track how many distinct events you've examined. A typical malware investigation might involve:
If your final investigation has fewer events than you examined, you're missing events.
For multi-host compromises, expect to multiply these numbers by the number of affected hosts (for key events, not all 60 C2 detections).
Investigation is not linear. It's a loop you run until the story is complete.
START with your initial event/detection/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 to investigation)
|
v
DECIDE: Is the story complete?
- Can I answer the completeness criteria?
- YES: Synthesize findings, present to user
- NO: Return to QUESTION
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? |
Investigate further when you see:
Stop investigating a particular thread when:
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.
Use these techniques as needed based on what you're investigating. This is a reference, not a checklist.
From an Event (atom + sid):
tool: get_event_by_atom
parameters:
oid: [oid]
sid: [sid]
atom: [atom]
From a Detection:
tool: get_detection
parameters:
oid: [oid]
detection_id: [detection-id]
Extract the triggering event atom, sensor ID, and timestamps.
From an LCQL Query:
tool: run_lcql_query
parameters:
oid: [oid]
query: [use generate_lcql_query first!]
limit: 100
Sensor Context:
tool: get_sensor_info
parameters:
oid: [oid]
sid: [sensor-id]
Direct Atom Navigation (preferred when you have atoms):
Get Parent:
tool: get_event_by_atom
parameters:
oid: [oid]
sid: [sid]
atom: [routing.parent from current event]
Get Children:
tool: get_atom_children
parameters:
oid: [oid]
sid: [sid]
atom: [routing.this from parent event]
LCQL Queries (when searching by attributes):
What to Look For:
DNS Requests:
Network Connections:
What to Look For:
File Operations:
Persistence Paths:
\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup, \Windows\System32\Tasks/etc/cron.d, /etc/systemd/system, /etc/init.dUser Activity:
Related Detections (remember: divide timestamps by 1000!):
tool: get_historic_detections
parameters:
oid: [oid]
sid: [sid]
start: [timestamp_in_seconds]
end: [timestamp_in_seconds]
limit: 50
Org-wide IOC Search (read search-iocs.md first!):
tool: search_iocs
parameters:
oid: [oid]
ioc_type: "ip" # Required: ip, domain, file_hash, file_path, file_name, user, etc.
ioc_value: "203.0.113.50" # Required: the IOC value to search
info_type: "locations" # Required: "summary" for counts, "locations" for sensor details
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:
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:
What to Document:
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:
tool: get_historic_detections
parameters:
oid: [oid]
sid: [sid]
start: [event_time_seconds - 3600] # 1 hour before
end: [event_time_seconds + 3600] # 1 hour after
limit: 100
Look for related suspicious activity:
Check for persistence mechanisms being installed:
Check for credential access:
Look for data staging/exfiltration:
What to Document:
The Question: Is this happening on other systems? How widespread is the compromise?
Investigation Steps:
Search for the malware hash org-wide (read search-iocs.md for full parameter details):
tool: search_iocs
parameters:
oid: [oid]
ioc_type: "file_hash"
ioc_value: "[malware_sha256]"
info_type: "locations"
Search for C2 IPs/domains org-wide (one search per IOC type):
tool: search_iocs
parameters:
oid: [oid]
ioc_type: "ip"
ioc_value: "[c2_ip]"
info_type: "locations"
tool: search_iocs
parameters:
oid: [oid]
ioc_type: "domain"
ioc_value: "[c2_domain]"
info_type: "locations"
Search for the malware file path pattern org-wide:
Search for the same command-line patterns:
Check for related detections org-wide:
tool: get_historic_detections
parameters:
oid: [oid]
# No sid - searches all sensors
start: [timestamp_seconds - 86400] # 24 hours before
end: [timestamp_seconds + 3600]
limit: 200
Filter results for same rule name or similar detection categories.
What to Document:
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:
Check for outbound lateral movement from this host:
Look for remote execution indicators:
Check authentication events:
Trace the infection path:
What to Document (REQUIRED - include in investigation even if negative):
finding note: "No evidence of lateral movement detected. Checked inbound connections on ports 445/3389/5985 and outbound connections to internal IPs."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 question notes |
If you cannot answer a question, document it explicitly as an unknown in your investigation notes using type: "question".
Build the investigation as you go. Don't wait until the end.
Use notes liberally to document your investigation journey. The investigation should tell the story of both:
Add investigation notes for:
Example investigation notes:
{"type": "observation", "content": "Ran LCQL query for parent PID 2476 - no results found. Parent process may predate telemetry window."}
{"type": "observation", "content": "Searched org-wide for C2 IP 35.232.8.38 using get_historic_detections - found second affected host desktop-c2a1841."}
{"type": "finding", "content": "No lateral movement detected. Checked inbound/outbound connections on ports 445/3389/5985 between both affected hosts - no direct connections found."}
{"type": "hypothesis", "content": "Both hosts may have been independently compromised via same phishing campaign rather than lateral spread."}
This documentation is valuable because:
Be inclusive - add events to the investigation if you investigated them, regardless of verdict. Include:
For each event you investigated:
{
"atom": "[event-atom]",
"sid": "[sensor-id]",
"relevance": "[Why this event matters - be specific about what it reveals]",
"verdict": "[malicious|suspicious|benign|unknown]",
"tags": ["phase:[tactic]", "mitre:[technique-id]", "timing:[marker]"]
}
For each IOC or entity of interest:
{
"type": "[ip|domain|hash|user|host|file_path|process]",
"value": "[entity_value]",
"first_seen": "[unix_epoch_ms]",
"last_seen": "[unix_epoch_ms]",
"context": "Provenance: [how discovered]. TI: [threat intel if available].",
"verdict": "[malicious|suspicious|benign|unknown]",
"related_events": ["[atom_refs]"]
}
Valid Entity Types (from investigation.schema.json)
| 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 |
host | Routing hostname | SERVER01 |
email | Email addresses from logs or alerts | [email protected] |
file_path | 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 |
other | Anything else that doesn't fit above | Registry key, mutex name, etc. |
| 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 |
Important: benign is a valuable verdict, not a reason to exclude an event. If you investigated something because it looked suspicious but determined it was legitimate, add it to the investigation with verdict benign and explain your reasoning in the relevance field. This documents what was checked and prevents future analysts from re-investigating the same activity.
Example benign event:
{
"atom": "abc123...",
"sid": "sensor-id",
"relevance": "Initially suspicious: svchost.exe with unusual parent. Cleared: Parent is services.exe (PID 684), this is normal Windows service startup. Command line contains legitimate service flags.",
"verdict": "benign",
"tags": ["investigated", "cleared"]
}
Use notes to capture your reasoning. Notes have a type field that must be one of the valid enum values.
{
"type": "[observation|hypothesis|finding|conclusion|action_item|question]",
"content": "[Your note content]",
"timestamp": "[unix_epoch_ms]",
"related_events": ["[optional atom refs]"],
"related_detections": ["[optional detection ids]"],
"resolved": false // Only for action_item and question types
}
IMPORTANT: Timestamp for Notes
The timestamp field should be the current time in milliseconds (Unix epoch) when you create the note - NOT an event timestamp from the investigation. This records when the analyst made the observation/finding, creating an audit trail of the investigation process itself.
To get the current timestamp in milliseconds, use: date +%s%3N (bash) or Date.now() (JavaScript).
IMPORTANT: Valid Note Types (from investigation.schema.json)
| Type | When to Use | Example |
|---|---|---|
observation | Raw facts observed during investigation | "Process rundll32.exe spawned without arguments at 19:39:10" |
hypothesis | Working theory to be tested | "Hypothesis: This may be Cobalt Strike based on the beaconing pattern" |
finding | Confirmed conclusion backed by evidence | "FINDING: Active C2 communication to 35.232.8.38 confirmed via 60+ network connections" |
conclusion | Final assessment of the investigation | "CONCLUSION: This is a true positive - active malware with C2 capability" |
action_item | Recommended next steps (can mark resolved=true when done) | "ACTION: Isolate host immediately to stop C2 communication" |
question | Unanswered questions (can mark resolved=true when answered) | "QUESTION: How was the malware initially delivered? No evidence of phishing or exploit found." |
Invalid types will cause API errors. Do NOT use types like "recommendation", "summary", "ioc", etc.
Best Practice Note Structure:
findingfindingaction_item type (NOT "recommendation")question typeDocument the attack chain when you've identified it:
ATTACK CHAIN: [Phase 1] -> [Phase 2] -> [Phase 3]
Techniques: [T1566] -> [T1059.001] -> [T1547.001]
Dwell Time: [first observed] to [last observed]
When you can confidently identify techniques, apply tags:
phase:initial-access, phase:execution, phase:persistence, etc.mitre:T1566, mitre:T1059.001, etc.timing:first-observed, timing:pivot-point, timing:detection-triggerconfidence:high, confidence:medium, confidence:lowFor MITRE reference, fetch from: https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/enterprise-attack/enterprise-attack.json
See Investigation Guide for complete tag format reference.
The complete investigation record:
{
"name": "[investigation_name]",
"description": "Investigation starting from [starting_point_description]",
"status": "in_progress",
"priority": "[critical|high|medium|low|informational]",
"events": [...],
"detections": [
{
"detection_id": "[detection-id]",
"tags": ["phase:[tactic]", "mitre:[technique-id]"]
}
],
"entities": [...],
"notes": [...],
"summary": "[executive summary - what happened, impact, current state]"
}
| Priority | Indicators |
|---|---|
critical | Active C2, ransomware, credential theft, ongoing exfiltration |
high | Malware drops, persistence mechanisms, lateral movement attempts |
medium | Unusual but not clearly malicious, potential false positives |
low | Minor anomalies, informational findings |
informational | Clean investigation, no threats found |
If user doesn't provide a name, auto-generate:
[threat-indicator]-[hostname]-[date]
Examples:
encoded-powershell-SERVER01-2024-01-20c2-communication-WORKSTATION5-2024-01-20You know you're done when:
Summarize for the user:
STOP - Before saving, verify your investigation is complete:
Event Coverage:
relevance explanationhost:hostname for multi-host investigationsDetection Coverage:
Entity/IOC Coverage:
Count Check: If you discovered 10+ events during investigation but only have 3 in the record, GO BACK and add the rest.
Always confirm with user before saving:
tool: set_investigation
parameters:
oid: [oid]
investigation_name: [investigation_name]
investigation_data: [investigation_record]
lookup-lc-doc - For LCQL syntax and event schema referencedetection-engineering - For creating D&R rules based on investigation findingsthreat-report-evaluation - For evaluating threat reports and searching for IOCssensor-tasking - For live response and data collection from sensors during investigation (EDR sensors only: requires platform=windows/linux/macos AND arch!=usp_adapter)legion_config_hive/hives/schemas/investigation.schema.jsonStatus values: new, in_progress, pending_review, escalated, closed_false_positive, closed_true_positive
Priority values: critical, high, medium, low, informational
Verdict values: unknown, benign, suspicious, malicious
Entity types: ip, domain, hash, user, host, email, file_path, process, url, other
Note types: observation, hypothesis, finding, conclusion, action_item, question
Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
Comprehensive guides and best practices for Neon Serverless Postgres, covering setup, connection methods, authentication, and platform APIs.
Guide for setting up and using Firebase Authentication. Use this skill when the user's app requires user sign-in, user management, or secure data access using auth rules.
A skill to evaluate how secure Firestore security rules are. Use this when Firestore security rules are updated to ensure that the generated rules are extremely secure and robust.
Official skill for integrating Firebase AI Logic (Gemini API) into web applications. Covers setup, multimodal inference, structured output, and security.
Complete Better Auth server and client setup with database adapters, session management, plugins, and security configuration.
Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".
Complete Cloudflare platform integration with decision trees for compute, storage, AI, networking, security, and infrastructure-as-code.
Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.
Send, read, and manage Gmail messages, drafts, labels, and account settings.
Comprehensive website auditing across 230+ rules in 21 categories including SEO, performance, security, and accessibility.
Shared authentication, CLI syntax, and output formatting patterns for gws Google Workspace commands.
Discover your celebrity doppelgänger with StarByFace!
GeoSpy: Pricing, Features, FAQs, and Alternatives for AI Teams
Detect AI-generated voices to protect against audio fraud.
Ensure Your Content's Originality with AI Plagiarism Checker
Upscale images by 400% without quality loss
Protect your social media from copyright disputes
Accurately Detect AI-Generated Content with TheChecker.AI
Chrome extension that detects and flags AI-generated content