Install
$ agentstack add skill-willwebster5-agent-skills-logscale-security-queries Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Dangerous shell/eval execution.
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ● Dynamic code execution Used
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
CrowdStrike LogScale Security Query Development
Expert assistance for developing security detection queries and hunting rules in CrowdStrike LogScale (formerly Humio) using CQL syntax.
When to Use This Skill
Use this skill when you need to:
- Write or optimize LogScale/CQL security queries
- Build threat detection rules with risk categorization
- Fix CQL syntax errors (especially case statements)
- Create investigation playbooks and hunting queries
- Develop queries for AWS CloudTrail, Entra ID, or CrowdStrike EDR
- Generate actionable security outputs with user context and remediation steps
- Build behavioral rules using
correlate()for multi-event detection - Create attack chain detections that span multiple events over time
Quick Start
Basic Query Structure
// 1. Filter relevant events
#event_simpleName=
|
// 2. Categorize risk
| case {
| _RiskLevel := "Critical" ;
| _RiskLevel := "High" ;
* | _RiskLevel := "Low" ;
}
// 3. Enrich with context
| match(file="entraidusers.csv", field=UserPrincipalName, include=[DisplayName])
// 4. Generate output
| table([_RiskLevel, DisplayName, ])
Critical Case Statement Rules
// ALWAYS use test() for numeric comparisons
| case {
test(FailedLogins > 5) | _Severity := "Critical" ; // ✅ CORRECT
FailedLogins > 5 | _Severity := "Critical" ; // ❌ WRONG
}
// AND/OR ARE supported in case branches (contrary to earlier docs)
// ✅ WORKS in case statements:
| case {
DetectionTier = "RAPID" AND UniqueIPs > 1 | RiskScore := 90;
UniqueIPs > 1 AND UniqueDevices > 1 | AttackPattern := "Distributed";
* | RiskScore := 50;
}
// Use composite keys when AND/OR is cleaner for string matching
| _Key := format("%s-%s", field=[Type, Location])
| case {
_Key="Admin-External" | _Risk := "High" ;
* | _Risk := "Low" ;
}
// ALWAYS include default branch
| case {
Status="Active" | _Label := "Active" ;
* | _Label := "Unknown" ; // ✅ Required
}
Behavioral Rules with correlate()
For multi-event pattern detection (attack chains, behavioral sequences):
correlate(
FailedLogin: {
event.outcome="failure" event.action=/UserLogon/
},
SuccessLogin: {
event.outcome="success" event.action=/UserLogon/
| user.email FailedLogin.user.email
},
sequence=true,
within=30m,
globalConstraints=[user.email]
)
Key correlate() concepts:
- Named queries:
FailedLogin: { ... }- each event pattern has a name - Link operator ``: Correlates fields between queries
sequence=true: Events must occur in orderwithin=30m: Time window constraintglobalConstraints: Fields all events must share
See [correlate-function.md](correlate-function.md) for complete syntax reference.
Core Principles
1. Actionable Over Raw
- Include display names, risk scores, and specific actions
- Provide categorized outputs, not just event dumps
- Add business context and investigation IDs
2. Syntax Precision
- Use
test()for all comparisons (>, =, 5)` - Not equal:
test(Field != "value") - Field comparison:
test(Field1 > Field2) - Simple equality:
Field="value"(no test() needed) - Regex:
Field=/pattern/(no test() needed)
AND/OR in Case Statements
AND/OR works in case branches for combining conditions:
| case {
DetectionTier = "RAPID" AND UniqueIPs > 1 | RiskScore := 90;
entra.privilege_category="global_admin" AND CountryRisk!="low" | CompositeRiskScore := CompositeRiskScore + 25;
* | RiskScore := 50;
}
Composite keys are still useful for complex string-based matching:
| _Key := format("%s-%s-%s", field=[Protocol, Port, DestIP])
| case {
_Key="tcp-22-0.0.0.0/0" | _Risk := "Critical" ;
_Key=/tcp-(80|443)-.*/ | _Risk := "Low" ;
}
Key Functions Quick Reference
| Function | Purpose | Example | |----------|---------|---------| | test() | Numeric comparison in case/filter | test(count > 5) | | if() | Conditional value assignment | if(field, then=a, else=b) | | format() | String formatting | format("%s-%s", field=[a, b]) | | coalesce() | First non-null value | coalesce([f1, f2], as=out) | | defineTable() | Historical baseline | defineTable(query={...}, start=7d) | | match() | CSV/table lookup | match(file="x.csv", field=f) | | selfJoinFilter() | Multi-event correlation | selfJoinFilter(field=[aid], where=[...]) | | session() | Time-bounded grouping | session([...], maxpause=15m) | | array:contains() | Array membership | array:contains(array="f[]", value="v") | | objectArray:eval() | Iterate object arrays | objectArray:eval("arr[]", ...) | | shannonEntropy() | String randomness | shannonEntropy(DomainName) | | ipLocation() | GeoIP enrichment | ipLocation(source.ip) | | asn() | ASN organization lookup | asn(source.ip) | | cidr() | Subnet membership | cidr(ip, subnet=["10.0.0.0/8"]) | | now() | Current time (epoch ms) | _current := now() | | formatDuration() | Duration display | formatDuration(ms, from=ms, precision=2) |
See [reference.md](reference.md) for complete syntax documentation.
Link Operator for correlate()
// The operator links fields between named queries
correlate(
Query1: { filter1 },
Query2: {
filter2
| fieldA Query1.fieldB // Links fieldA to Query1.fieldB
},
within=1h
)
// Output fields are prefixed: Query1.fieldB, Query2.fieldA
Supporting Files
- [correlate-function.md](correlate-function.md) - Complete
correlate()function reference for behavioral rules and multi-event detection - [case-statements.md](case-statements.md) - Complete case statement syntax guide with 12 patterns and comprehensive error troubleshooting
- [troubleshooting.md](troubleshooting.md) - Error catalog, debugging methodology, emergency fixes
- [query-patterns.md](query-patterns.md) - Common detection patterns and reusable templates
- [investigation-playbooks.md](investigation-playbooks.md) - Structured hunting methodology and IR workflows
- [examples.md](examples.md) - Production-ready query examples for AWS, Entra ID, CrowdStrike
- [reference.md](reference.md) - Complete CQL syntax reference and platform integrations
Workflow
- Define objective - What threat/behavior are you detecting?
- Start with basic filter - Get relevant events with simple filters
- Add categorization - Implement risk-based logic with case statements
- Enrich context - Add user data, geo, timeline using joins/lookups
- Generate output - Create actionable format with display names and actions
- Validate query - Use the CLI validator before deployment
- Test and refine - Validate against historical data, adjust false positives
Query Validation (AI-Assisted Detection Engineering)
When creating or modifying detection templates, always validate queries before committing:
Validate Query CLI Command
# Validate query from a detection template
python scripts/resource_deploy.py validate-query --template
# Validate inline query
python scripts/resource_deploy.py validate-query --query '#Vendor="sase" | count()'
# Validate query from file
python scripts/resource_deploy.py validate-query --file /tmp/query.txt
Output
VALID(exit code 0) - Query syntax is correctINVALID:(exit code 1) - Query has syntax errors
AI Workflow for Detection Development
- Write the detection template with
search.filterquery - Run validation:
python scripts/resource_deploy.py validate-query --template - If INVALID, review the query for common CQL issues:
- Case statement syntax (missing
test(), missing default branch*) - Incorrect use of
if()function (usecasestatements instead) - AND/OR operators in case conditions (use composite keys)
- Comparison operators without
test()wrapper
- Fix and re-validate until
VALID - Run full plan:
python scripts/resource_deploy.py plan --resources=detection
Common Validation Failures
| Error Pattern | Likely Cause | Fix | |---------------|--------------|-----| | NotAFunctionArgumentOperator | Using = in function args like count(x, where=field="value") | Use case statement to create flag field, then sum() | | UnrecognizedNamedArgumentNoSuggestions | Wrong if() syntax | Use case statement instead of if() | | ArraysNotSupportedHere | Positional args in if() | Use named params: if(condition, then=x, else=y) | | Generic syntax error | Case statement issues | Check for test(), default branch, no AND/OR | | Unknown error with groupBy | Named assignment := in function list | Use as= for count/sum/min/max, use original field name for collect() | | Unknown error with collect | Using as= or := with collect() | collect() doesn't support naming - use original field name after groupBy |
Debugging "Unknown Error"
When you get INVALID: Syntax error: Unknown error, isolate the problem:
# 1. Stash changes, validate original
git stash && python scripts/resource_deploy.py validate-query --template
git stash pop
# 2. Test individual syntax patterns
python scripts/resource_deploy.py validate-query --query '#Vendor="aws" | groupBy([x], function=[count()])'
# 3. Binary search - comment out half the query and validate
See [troubleshooting.md](troubleshooting.md) for the full debugging methodology.
Platform Limitations
Case Statements
- ❌ No nested case statements (use sequential case blocks instead)
- ❌ No comparisons (>, 5`)
- ✅ Use sequential case statements for complex multi-step logic
- ✅ Wrap numeric comparisons in test()
- ✅ Create fields first, use in next case statement
- ✅ Always include default branch (
*) - ✅ Use
as=for count/sum/min/max in groupBy
correlate() Function
- ❌ Cannot use after aggregators (groupBy, count, etc.)
- ❌ Cannot appear inside function parameters
- ❌ Cannot use aggregate functions within queries
- ❌ Only `` operator for linking (no other comparisons)
- ❌ Results must fit within memory quota
- ✅ Supports 3+ queries (unlike join which only supports 2)
- ✅ Use
globalConstraintsto simplify links - ✅ Use
sequence=trueonly when event order matters
Requirements
This skill works with:
- CrowdStrike LogScale / Humio
- CQL (CrowdStrike Query Language)
- CSV lookup files (entraidusers.csv, entraidgroups.csv)
- Custom functions (awsserviceaccount_detector, etc.)
Need Help?
- Syntax error? → Check [troubleshooting.md](troubleshooting.md)
- Case statement failing? → See [case-statements.md](case-statements.md)
- Need a pattern? → Browse [query-patterns.md](query-patterns.md)
- Building detection? → See [examples.md](examples.md)
- Investigation workflow? → See [investigation-playbooks.md](investigation-playbooks.md)
- Behavioral rules / correlate()? → See [correlate-function.md](correlate-function.md)
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: willwebster5
- Source: willwebster5/agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.