security-detections-mcp 1.4.1 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +279 -2
- package/dist/db/cache.d.ts +61 -0
- package/dist/db/cache.js +141 -0
- package/dist/db/connection.d.ts +42 -0
- package/dist/db/connection.js +206 -0
- package/dist/db/detections.d.ts +224 -0
- package/dist/db/detections.js +944 -0
- package/dist/db/dynamic.d.ts +83 -0
- package/dist/db/dynamic.js +462 -0
- package/dist/db/index.d.ts +13 -0
- package/dist/db/index.js +58 -0
- package/dist/db/knowledge.d.ts +150 -0
- package/dist/db/knowledge.js +762 -0
- package/dist/db/patterns.d.ts +117 -0
- package/dist/db/patterns.js +912 -0
- package/dist/db/schema.d.ts +17 -0
- package/dist/db/schema.js +213 -0
- package/dist/db/stories.d.ts +34 -0
- package/dist/db/stories.js +122 -0
- package/dist/db.d.ts +38 -0
- package/dist/db.js +237 -3
- package/dist/handlers/index.d.ts +3 -0
- package/dist/handlers/index.js +4 -0
- package/dist/handlers/prompts.d.ts +23 -0
- package/dist/handlers/prompts.js +128 -0
- package/dist/handlers/resources.d.ts +27 -0
- package/dist/handlers/resources.js +326 -0
- package/dist/handlers/sampling.d.ts +62 -0
- package/dist/handlers/sampling.js +181 -0
- package/dist/handlers/tools.d.ts +15 -0
- package/dist/handlers/tools.js +8 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +35 -3659
- package/dist/resources/index.d.ts +48 -0
- package/dist/resources/index.js +483 -0
- package/dist/server.d.ts +19 -0
- package/dist/server.js +232 -0
- package/dist/tools/autonomous/index.d.ts +23 -0
- package/dist/tools/autonomous/index.js +712 -0
- package/dist/tools/cache/index.d.ts +11 -0
- package/dist/tools/cache/index.js +257 -0
- package/dist/tools/detections/analysis.d.ts +1 -0
- package/dist/tools/detections/analysis.js +160 -0
- package/dist/tools/detections/comparison.d.ts +1 -0
- package/dist/tools/detections/comparison.js +317 -0
- package/dist/tools/detections/filters.d.ts +1 -0
- package/dist/tools/detections/filters.js +455 -0
- package/dist/tools/detections/index.d.ts +12 -0
- package/dist/tools/detections/index.js +25 -0
- package/dist/tools/detections/search.d.ts +1 -0
- package/dist/tools/detections/search.js +154 -0
- package/dist/tools/dynamic/index.d.ts +16 -0
- package/dist/tools/dynamic/index.js +426 -0
- package/dist/tools/engineering/index.d.ts +12 -0
- package/dist/tools/engineering/index.js +645 -0
- package/dist/tools/index.d.ts +20 -0
- package/dist/tools/index.js +61 -0
- package/dist/tools/knowledge/index.d.ts +13 -0
- package/dist/tools/knowledge/index.js +630 -0
- package/dist/tools/meta/index.d.ts +27 -0
- package/dist/tools/meta/index.js +419 -0
- package/dist/tools/registry.d.ts +41 -0
- package/dist/tools/registry.js +76 -0
- package/dist/tools/stories/index.d.ts +1 -0
- package/dist/tools/stories/index.js +125 -0
- package/dist/types/detection.d.ts +165 -0
- package/dist/types/detection.js +5 -0
- package/dist/types/dynamic.d.ts +116 -0
- package/dist/types/dynamic.js +6 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/types/index.js +14 -0
- package/dist/types/knowledge.d.ts +146 -0
- package/dist/types/knowledge.js +6 -0
- package/dist/types/meta.d.ts +190 -0
- package/dist/types/meta.js +6 -0
- package/dist/types/stats.d.ts +59 -0
- package/dist/types/stats.js +5 -0
- package/dist/types/story.d.ts +42 -0
- package/dist/types/story.js +5 -0
- package/dist/types.d.ts +10 -177
- package/dist/types.js +10 -2
- package/dist/utils/helpers.d.ts +66 -0
- package/dist/utils/helpers.js +135 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +6 -0
- package/package.json +11 -4
package/README.md
CHANGED
|
@@ -4,6 +4,57 @@ An MCP (Model Context Protocol) server that lets LLMs query a unified database o
|
|
|
4
4
|
|
|
5
5
|
[](https://cursor.com/en/install-mcp?name=security-detections&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInNlY3VyaXR5LWRldGVjdGlvbnMtbWNwIl0sImVudiI6eyJTSUdNQV9QQVRIUyI6Ii9wYXRoL3RvL3NpZ21hL3J1bGVzLC9wYXRoL3RvL3NpZ21hL3J1bGVzLXRocmVhdC1odW50aW5nIiwiU1BMVU5LX1BBVEhTIjoiL3BhdGgvdG8vc2VjdXJpdHlfY29udGVudC9kZXRlY3Rpb25zIiwiU1RPUllfUEFUSFMiOiIvcGF0aC90by9zZWN1cml0eV9jb250ZW50L3N0b3JpZXMiLCJFTEFTVElDX1BBVEhTIjoiL3BhdGgvdG8vZGV0ZWN0aW9uLXJ1bGVzL3J1bGVzIiwiS1FMX1BBVEhTIjoiL3BhdGgvdG8va3FsLXJ1bGVzIn19)
|
|
6
6
|
|
|
7
|
+
## 🐛 Version 2.1.1 (Bug Fix)
|
|
8
|
+
|
|
9
|
+
- **Fixed Windows EBUSY crash** - SQLite database recreation now handles Windows file locking with retry logic. Previously, Windows users would get `EBUSY: resource busy or locked` on startup.
|
|
10
|
+
- **SQLite journal cleanup** - WAL, SHM, and journal companion files are now cleaned up during database recreation.
|
|
11
|
+
- **Windows CI** - Added Windows to the CI matrix. Build, tests, and full Sigma indexing pipeline now run on both Linux and Windows.
|
|
12
|
+
- **Cross-platform test suite** - New `tests/cross-platform-test.js` validates database lifecycle on all platforms. New `tests/ci-integration-test.js` downloads and indexes 3,200+ Sigma rules to validate the full pipeline.
|
|
13
|
+
|
|
14
|
+
## 🚀 Version 2.1 Features
|
|
15
|
+
|
|
16
|
+
**Security Detections MCP v2.1** introduces powerful new capabilities for detection engineering intelligence, analytical memory, autonomous analysis, and advanced MCP protocol features:
|
|
17
|
+
|
|
18
|
+
### What's New in v2.1
|
|
19
|
+
- **Elicitation Support** - Server can request user confirmation for destructive operations (when client supports it)
|
|
20
|
+
- **Sampling Integration** - LLM-enhanced analysis via MCP sampling (when client supports it)
|
|
21
|
+
- **Resource Subscriptions** - Subscribe to resource changes for live updates
|
|
22
|
+
- **Enhanced Error Handling** - Safe JSON parsing and comprehensive error wrapping
|
|
23
|
+
- **Dynamic Pattern Extraction** - Improved field/function extraction without hardcoded limitations
|
|
24
|
+
- **71+ Tools** - Extended tool suite with 2 new sampling-related tools
|
|
25
|
+
|
|
26
|
+
### Detection Engineering Intelligence (8 Tools)
|
|
27
|
+
- **Pattern Learning** - Automatically extracts and learns patterns from 4 detection formats (SPL, Sigma, KQL, Elastic)
|
|
28
|
+
- **Template Generation** - Creates reusable detection templates from learned patterns
|
|
29
|
+
- **Field & Macro References** - Tracks commonly used fields, macros, and functions across detections
|
|
30
|
+
- **Feedback Learning** - Learns from user corrections and improvements to enhance future suggestions
|
|
31
|
+
|
|
32
|
+
### Knowledge Graph / Tribal Knowledge (12 Tools)
|
|
33
|
+
- **Analytical Memory** - Persistent knowledge graph that remembers WHY decisions were made, not just WHAT was detected
|
|
34
|
+
- **Entity Management** - Create and relate entities (threats, techniques, detections, data sources)
|
|
35
|
+
- **Decision Logging** - Record analytical reasoning and decision-making context for future reference
|
|
36
|
+
- **Learning Capture** - Store insights, patterns, and lessons learned that help future agents understand context
|
|
37
|
+
|
|
38
|
+
### Dynamic Tables (6 Tools)
|
|
39
|
+
- **Custom Analysis Storage** - Create tables on-the-fly for storing analysis results, gap assessments, or custom data
|
|
40
|
+
- **Flexible Schema** - Define your own table structure for any analysis workflow
|
|
41
|
+
- **Query Interface** - Query stored analysis data with SQL-like operations
|
|
42
|
+
- **Persistent Storage** - Tables persist across sessions for long-term analysis tracking
|
|
43
|
+
|
|
44
|
+
### Comprehensive Pattern Extraction
|
|
45
|
+
- **Multi-Format Support** - Extracts patterns from Sigma, Splunk SPL, KQL, and Elastic queries
|
|
46
|
+
- **10,235+ Indexed Patterns** - Comprehensive pattern library covering 528+ MITRE techniques
|
|
47
|
+
- **Cross-Format Insights** - Learn how different platforms detect the same techniques
|
|
48
|
+
|
|
49
|
+
### Expanded Tool Suite
|
|
50
|
+
- **71+ Total Tools** (vs ~40 in v1.0)
|
|
51
|
+
- **Engineering Tools** (8) - Pattern learning, template generation, field analysis
|
|
52
|
+
- **Knowledge Tools** (12) - Knowledge graph, entity relations, decision logging
|
|
53
|
+
- **Dynamic Tools** (6) - Custom table creation and querying
|
|
54
|
+
- **Autonomous Tools** (5) - Self-directed analysis, LLM-enhanced analysis, sampling status
|
|
55
|
+
- **Meta/Template Tools** (5) - Query templates and workflow shortcuts
|
|
56
|
+
- **Cache Tools** (4) - Index management, saved queries
|
|
57
|
+
|
|
7
58
|
## 🆕 MCP Prompts - Expert Detection Workflows
|
|
8
59
|
|
|
9
60
|
This server includes **11 pre-built MCP Prompts** that provide structured, expert-level workflows for common security detection tasks. Instead of figuring out which tools to use and in what order, just ask for a prompt by name and get a comprehensive, professional analysis.
|
|
@@ -413,6 +464,77 @@ These tools do heavy processing server-side and return minimal, actionable data:
|
|
|
413
464
|
| `prioritize_gaps(threat_profile, source_type?)` | Analyze gaps with P0/P1/P2 prioritization and selection guidance |
|
|
414
465
|
| `plan_detection_sprint()` | Generate sprint configuration options with recommended backlog |
|
|
415
466
|
|
|
467
|
+
### Engineering Tools (8)
|
|
468
|
+
|
|
469
|
+
Detection engineering intelligence tools for pattern learning and template generation:
|
|
470
|
+
|
|
471
|
+
| Tool | Description |
|
|
472
|
+
|------|-------------|
|
|
473
|
+
| `extract_patterns(technique_id, source_type?)` | Extract detection patterns for a technique from all sources |
|
|
474
|
+
| `learn_pattern(technique_id, pattern, format)` | Teach the system a new pattern for a technique |
|
|
475
|
+
| `get_patterns(technique_id, format?)` | Retrieve learned patterns for a technique |
|
|
476
|
+
| `generate_template(technique_id, format, data_source)` | Generate detection template from learned patterns |
|
|
477
|
+
| `analyze_fields(technique_id)` | Analyze commonly used fields/macros for a technique |
|
|
478
|
+
| `get_field_references(field_name)` | Find all detections using a specific field or macro |
|
|
479
|
+
| `suggest_improvements(detection_id)` | Get AI suggestions for improving a detection based on patterns |
|
|
480
|
+
| `compare_patterns(technique_id)` | Compare patterns across different detection formats |
|
|
481
|
+
|
|
482
|
+
### Knowledge Tools (12)
|
|
483
|
+
|
|
484
|
+
Knowledge graph and tribal knowledge tools for analytical memory:
|
|
485
|
+
|
|
486
|
+
| Tool | Description |
|
|
487
|
+
|------|-------------|
|
|
488
|
+
| `create_entity(name, type, properties)` | Create an entity in the knowledge graph (threat, technique, detection, etc.) |
|
|
489
|
+
| `create_relation(source_entity, relation_type, target_entity, reasoning)` | Create a relationship between entities with reasoning |
|
|
490
|
+
| `search_knowledge(query, entity_type?)` | Search the knowledge graph for entities and relations |
|
|
491
|
+
| `get_entity(name)` | Get full details of an entity including all relations |
|
|
492
|
+
| `log_decision(context, decision, reasoning, tags)` | Log an analytical decision with full context for future reference |
|
|
493
|
+
| `get_relevant_decisions(context, tags?)` | Retrieve relevant past decisions for current context |
|
|
494
|
+
| `add_learning(insight, category, tags)` | Store a learning or insight for future agents |
|
|
495
|
+
| `get_learnings(category?, tags?)` | Retrieve stored learnings by category or tags |
|
|
496
|
+
| `link_detection_to_entity(detection_id, entity_name, relation_type)` | Link a detection to a knowledge graph entity |
|
|
497
|
+
| `get_entity_detections(entity_name)` | Get all detections related to an entity |
|
|
498
|
+
| `update_entity(name, properties)` | Update entity properties in the knowledge graph |
|
|
499
|
+
| `delete_entity(name)` | Remove an entity from the knowledge graph |
|
|
500
|
+
|
|
501
|
+
### Dynamic Tools (6)
|
|
502
|
+
|
|
503
|
+
Custom table creation and querying for flexible analysis storage:
|
|
504
|
+
|
|
505
|
+
| Tool | Description |
|
|
506
|
+
|------|-------------|
|
|
507
|
+
| `create_table(table_name, schema)` | Create a custom table with defined schema for analysis storage |
|
|
508
|
+
| `insert_row(table_name, row_data)` | Insert a row of data into a custom table |
|
|
509
|
+
| `query_table(table_name, query, limit?)` | Query a custom table with SQL-like syntax |
|
|
510
|
+
| `list_tables()` | List all custom tables you've created |
|
|
511
|
+
| `get_table_schema(table_name)` | Get the schema of a custom table |
|
|
512
|
+
| `delete_table(table_name)` | Delete a custom table |
|
|
513
|
+
|
|
514
|
+
### Autonomous Tools (5)
|
|
515
|
+
|
|
516
|
+
Self-directed analysis tools that work independently:
|
|
517
|
+
|
|
518
|
+
| Tool | Description |
|
|
519
|
+
|------|-------------|
|
|
520
|
+
| `auto_analyze_coverage(threat_profiles?, store_results?)` | Comprehensive coverage analysis across threat profiles |
|
|
521
|
+
| `auto_gap_report(report_name?, compare_sources?)` | Generate executive-level gap reports with prioritized recommendations |
|
|
522
|
+
| `auto_compare_sources(techniques?, focus_tactic?)` | Compare detection coverage across all sources with reasoning |
|
|
523
|
+
| `llm_enhanced_analysis(analysis_type, threat_profile?)` | LLM-enhanced analysis via MCP sampling (when supported) |
|
|
524
|
+
| `check_sampling_status()` | Check if MCP sampling is available for LLM-enhanced analysis |
|
|
525
|
+
|
|
526
|
+
### Meta/Template Tools (5)
|
|
527
|
+
|
|
528
|
+
Query templates and workflow shortcuts:
|
|
529
|
+
|
|
530
|
+
| Tool | Description |
|
|
531
|
+
|------|-------------|
|
|
532
|
+
| `save_template(name, tool_calls, description)` | Save a sequence of tool calls as a reusable template |
|
|
533
|
+
| `run_template(template_name, variables?)` | Execute a saved template with optional variable substitution |
|
|
534
|
+
| `list_templates()` | List all saved templates |
|
|
535
|
+
| `get_template(template_name)` | Get details of a saved template |
|
|
536
|
+
| `delete_template(template_name)` | Delete a saved template |
|
|
537
|
+
|
|
416
538
|
## MCP Prompts - Detailed Reference
|
|
417
539
|
|
|
418
540
|
MCP Prompts are pre-built, expert-level workflows that guide Claude through complex analysis tasks. They ensure consistent, comprehensive results by defining exactly which tools to use and in what order.
|
|
@@ -753,6 +875,55 @@ Supports multiple KQL repositories:
|
|
|
753
875
|
- Title derived from filename
|
|
754
876
|
- Lightweight queries for kqlsearch.com
|
|
755
877
|
|
|
878
|
+
## ⚠️ Limitations & Transparency
|
|
879
|
+
|
|
880
|
+
We believe in being honest about what this tool can and cannot do. Here are the current limitations:
|
|
881
|
+
|
|
882
|
+
### Pattern Extraction Limitations
|
|
883
|
+
|
|
884
|
+
The Detection Engineering Intelligence features extract patterns **dynamically** from your detection corpus, but have some inherent limitations:
|
|
885
|
+
|
|
886
|
+
| Format | Field Extraction | Notes |
|
|
887
|
+
|--------|-----------------|-------|
|
|
888
|
+
| **Splunk SPL** | ✅ Excellent | Extracts from data models, `by` clauses, `stats` commands, `where` filters |
|
|
889
|
+
| **Sigma** | ✅ Excellent | Full YAML parsing of detection logic |
|
|
890
|
+
| **KQL** | ⚠️ Good | Dynamic extraction from `project`, `extend`, `where`, `summarize by`, `join on` |
|
|
891
|
+
| **Elastic** | ⚠️ Good | Dynamic extraction from `field:value` patterns, EQL `where` clauses |
|
|
892
|
+
|
|
893
|
+
**What this means:**
|
|
894
|
+
- **SPL and Sigma**: Highly accurate pattern extraction from full detection corpus
|
|
895
|
+
- **KQL and Elastic**: Uses regex-based dynamic extraction that catches most patterns, but may miss:
|
|
896
|
+
- Unusual field naming conventions
|
|
897
|
+
- Complex nested expressions
|
|
898
|
+
- Custom functions or operators
|
|
899
|
+
|
|
900
|
+
### Coverage Analysis Limitations
|
|
901
|
+
|
|
902
|
+
- **MITRE mappings depend on source data** - If a detection doesn't have MITRE tags, we can't map it
|
|
903
|
+
- **Gap analysis is relative** - "Gaps" are based on threat profiles, not absolute coverage requirements
|
|
904
|
+
- **Cross-platform comparisons** - Different platforms have different capabilities; raw counts don't tell the whole story
|
|
905
|
+
|
|
906
|
+
### Client Feature Availability
|
|
907
|
+
|
|
908
|
+
Some v2.1 features depend on **client support**:
|
|
909
|
+
|
|
910
|
+
| Feature | Requires | Fallback |
|
|
911
|
+
|---------|----------|----------|
|
|
912
|
+
| **Elicitation** | Client MCP elicitation support | Parameter-based confirmation (`confirm: true`) |
|
|
913
|
+
| **Sampling** | Client MCP sampling support | Direct analysis without LLM enhancement |
|
|
914
|
+
| **Resource Subscriptions** | Client subscription support | Poll resources manually |
|
|
915
|
+
|
|
916
|
+
**Note**: As of January 2025, Cursor may not fully support elicitation and sampling. The MCP gracefully falls back to alternative methods when these features aren't available.
|
|
917
|
+
|
|
918
|
+
### Reporting Issues
|
|
919
|
+
|
|
920
|
+
Found a limitation or inaccuracy? Please [open an issue](https://github.com/MHaggis/Security-Detections-MCP/issues) with:
|
|
921
|
+
1. The detection format (Sigma, Splunk, Elastic, KQL)
|
|
922
|
+
2. An example query that wasn't extracted correctly
|
|
923
|
+
3. Expected vs actual behavior
|
|
924
|
+
|
|
925
|
+
We continuously improve the pattern extraction based on community feedback.
|
|
926
|
+
|
|
756
927
|
## Development
|
|
757
928
|
|
|
758
929
|
```bash
|
|
@@ -762,6 +933,12 @@ npm install
|
|
|
762
933
|
# Build
|
|
763
934
|
npm run build
|
|
764
935
|
|
|
936
|
+
# Run tests
|
|
937
|
+
npm test
|
|
938
|
+
|
|
939
|
+
# Lint (TypeScript strict mode)
|
|
940
|
+
npm run lint
|
|
941
|
+
|
|
765
942
|
# Run with paths
|
|
766
943
|
SIGMA_PATHS="./detections/sigma/rules" \
|
|
767
944
|
SPLUNK_PATHS="./detections/splunk/detections" \
|
|
@@ -777,12 +954,112 @@ When fully indexed with all sources:
|
|
|
777
954
|
|
|
778
955
|
| Source | Count |
|
|
779
956
|
|--------|-------|
|
|
780
|
-
| Sigma Rules | ~3,
|
|
957
|
+
| Sigma Rules | ~3,200+ |
|
|
781
958
|
| Splunk ESCU | ~2,000+ |
|
|
782
959
|
| Elastic Rules | ~1,500+ |
|
|
783
960
|
| KQL Queries | ~420+ |
|
|
784
961
|
| Analytic Stories | ~330 |
|
|
785
|
-
| **Total** | **~7,200+** |
|
|
962
|
+
| **Total Detections** | **~7,200+** |
|
|
963
|
+
| **Indexed Patterns** | **10,235+** |
|
|
964
|
+
| **Techniques with Patterns** | **528+** |
|
|
965
|
+
| **Detection Formats** | **4** (Sigma, Splunk, Elastic, KQL) |
|
|
966
|
+
| **Total Tools** | **71+** |
|
|
967
|
+
| **MCP Prompts** | **11** |
|
|
968
|
+
| **MCP Resources** | **9 static + 5 templates** |
|
|
969
|
+
|
|
970
|
+
## 🧠 Tribal Knowledge
|
|
971
|
+
|
|
972
|
+
**Tribal Knowledge** is the analytical memory system that helps future agents understand WHY decisions were made, not just WHAT was detected. It's like having a senior analyst's notebook that persists across sessions.
|
|
973
|
+
|
|
974
|
+
### What is Tribal Knowledge?
|
|
975
|
+
|
|
976
|
+
Traditional detection systems store facts: "We have 5 detections for T1059.001." Tribal Knowledge stores reasoning: "We prioritized T1059.001 because it's used in 80% of ransomware attacks, and our current detections miss base64-encoded PowerShell, which is why we added detection X."
|
|
977
|
+
|
|
978
|
+
### Knowledge Graph Tables
|
|
979
|
+
|
|
980
|
+
The knowledge graph consists of four interconnected tables:
|
|
981
|
+
|
|
982
|
+
1. **Entities** - Things you care about (threats, techniques, detections, data sources, campaigns)
|
|
983
|
+
2. **Relations** - How entities connect ("APT29 uses T1059.001", "Detection X covers T1059.001")
|
|
984
|
+
3. **Decisions** - Analytical reasoning and decision-making context
|
|
985
|
+
4. **Learnings** - Insights, patterns, and lessons learned
|
|
986
|
+
|
|
987
|
+
### How It Helps Future Agents
|
|
988
|
+
|
|
989
|
+
When you log a decision like:
|
|
990
|
+
```json
|
|
991
|
+
log_decision(
|
|
992
|
+
context: "Ransomware gap analysis",
|
|
993
|
+
decision: "Prioritize T1486 (Data Encrypted for Impact)",
|
|
994
|
+
reasoning: "This is the final stage of ransomware attacks. Without detection here, we can't prevent data loss.",
|
|
995
|
+
tags: ["ransomware", "priority", "data-protection"]
|
|
996
|
+
)
|
|
997
|
+
```
|
|
998
|
+
|
|
999
|
+
Future agents can retrieve this context when analyzing ransomware coverage, understanding not just that T1486 is important, but WHY it was prioritized.
|
|
1000
|
+
|
|
1001
|
+
### Example Workflow
|
|
1002
|
+
|
|
1003
|
+
```
|
|
1004
|
+
1. Analyze ransomware gaps → identify_gaps("ransomware")
|
|
1005
|
+
2. Log decision → log_decision("Prioritized T1486 because...")
|
|
1006
|
+
3. Create entity → create_entity("Ransomware Campaign 2024", "threat")
|
|
1007
|
+
4. Link detection → link_detection_to_entity("det_123", "Ransomware Campaign 2024", "detects")
|
|
1008
|
+
5. Future agent → get_relevant_decisions("ransomware") → understands context
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
## 🔬 Detection Engineering Intelligence
|
|
1012
|
+
|
|
1013
|
+
**Detection Engineering Intelligence** learns patterns from your detection corpus and helps you create better detections faster.
|
|
1014
|
+
|
|
1015
|
+
### Pattern Learning from 4 Sources
|
|
1016
|
+
|
|
1017
|
+
The system automatically extracts patterns from:
|
|
1018
|
+
- **Sigma rules** - YAML-based detection logic
|
|
1019
|
+
- **Splunk SPL** - Search Processing Language queries
|
|
1020
|
+
- **KQL queries** - Microsoft Kusto Query Language
|
|
1021
|
+
- **Elastic queries** - Elastic Detection Rules (EQL, KQL, Lucene)
|
|
1022
|
+
|
|
1023
|
+
### Automatic Template Generation
|
|
1024
|
+
|
|
1025
|
+
When you need a detection for T1059.001 (PowerShell), the system:
|
|
1026
|
+
1. Analyzes all existing T1059.001 detections across formats
|
|
1027
|
+
2. Extracts common patterns (process names, command-line arguments, base64 encoding)
|
|
1028
|
+
3. Generates a template with placeholders for your specific environment
|
|
1029
|
+
4. Suggests improvements based on learned patterns
|
|
1030
|
+
|
|
1031
|
+
### Field and Macro References
|
|
1032
|
+
|
|
1033
|
+
The system tracks:
|
|
1034
|
+
- Which fields/macros are commonly used for each technique
|
|
1035
|
+
- Cross-platform field mappings (e.g., `process_name` in Splunk vs `ProcessName` in KQL)
|
|
1036
|
+
- Best practices for field usage in different contexts
|
|
1037
|
+
|
|
1038
|
+
### Learning from User Feedback
|
|
1039
|
+
|
|
1040
|
+
When you improve a detection or correct a pattern:
|
|
1041
|
+
- The system learns from your changes
|
|
1042
|
+
- Future template generation incorporates your improvements
|
|
1043
|
+
- Field suggestions become more accurate over time
|
|
1044
|
+
|
|
1045
|
+
### Example Workflow
|
|
1046
|
+
|
|
1047
|
+
```
|
|
1048
|
+
1. Extract patterns → extract_patterns("T1059.001")
|
|
1049
|
+
2. Review patterns → get_patterns("T1059.001", "splunk")
|
|
1050
|
+
3. Generate template → generate_template("T1059.001", "splunk", "Sysmon")
|
|
1051
|
+
4. Customize template → (edit generated detection)
|
|
1052
|
+
5. System learns → (automatically improves future templates)
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
## 📚 Documentation
|
|
1056
|
+
|
|
1057
|
+
For detailed information on v2.1 features:
|
|
1058
|
+
|
|
1059
|
+
- **[Architecture](docs/wiki/Architecture.md)** - System architecture and design decisions
|
|
1060
|
+
- **[Knowledge Graph](docs/wiki/Knowledge-Graph.md)** - Deep dive into tribal knowledge and knowledge graph usage
|
|
1061
|
+
- **[Engineering Intelligence](docs/wiki/Engineering-Intelligence.md)** - Pattern learning and template generation guide
|
|
1062
|
+
- **[Tools Reference](docs/wiki/Tools-Reference.md)** - Complete reference for all 71+ tools
|
|
786
1063
|
|
|
787
1064
|
## 🔗 Using with MITRE ATT&CK MCP
|
|
788
1065
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache Database Module
|
|
3
|
+
*
|
|
4
|
+
* Saved queries and results caching functionality.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Initialize the saved queries table.
|
|
8
|
+
* Called automatically when needed.
|
|
9
|
+
*/
|
|
10
|
+
export declare function initSavedQueriesTable(): void;
|
|
11
|
+
/**
|
|
12
|
+
* Save a query result to the cache.
|
|
13
|
+
*
|
|
14
|
+
* @param name - Unique name for the saved query
|
|
15
|
+
* @param queryType - Type of query (e.g., 'search', 'coverage', 'gaps')
|
|
16
|
+
* @param queryParams - Parameters used for the query
|
|
17
|
+
* @param result - The result to cache
|
|
18
|
+
* @param ttlMinutes - Optional time-to-live in minutes
|
|
19
|
+
* @returns The generated ID for the saved query
|
|
20
|
+
*/
|
|
21
|
+
export declare function saveQueryResult(name: string, queryType: string, queryParams: Record<string, unknown>, result: unknown, ttlMinutes?: number): string;
|
|
22
|
+
/**
|
|
23
|
+
* Get a saved query result by name.
|
|
24
|
+
* Returns null if not found or expired.
|
|
25
|
+
*
|
|
26
|
+
* @param name - Name of the saved query
|
|
27
|
+
* @returns The cached result or null
|
|
28
|
+
*/
|
|
29
|
+
export declare function getSavedQuery(name: string): unknown | null;
|
|
30
|
+
/**
|
|
31
|
+
* List all saved queries, optionally filtered by type.
|
|
32
|
+
*
|
|
33
|
+
* @param queryType - Optional filter by query type
|
|
34
|
+
* @returns Array of saved query metadata
|
|
35
|
+
*/
|
|
36
|
+
export declare function listSavedQueries(queryType?: string): Array<{
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
query_type: string;
|
|
40
|
+
created_at: string;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Delete a saved query by name.
|
|
44
|
+
*
|
|
45
|
+
* @param name - Name of the saved query to delete
|
|
46
|
+
* @returns True if a query was deleted, false otherwise
|
|
47
|
+
*/
|
|
48
|
+
export declare function deleteSavedQuery(name: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Delete all expired saved queries.
|
|
51
|
+
*
|
|
52
|
+
* @returns Number of queries deleted
|
|
53
|
+
*/
|
|
54
|
+
export declare function cleanupExpiredQueries(): number;
|
|
55
|
+
/**
|
|
56
|
+
* Get a saved query result by ID.
|
|
57
|
+
*
|
|
58
|
+
* @param id - ID of the saved query
|
|
59
|
+
* @returns The cached result or null
|
|
60
|
+
*/
|
|
61
|
+
export declare function getSavedQueryById(id: string): unknown | null;
|
package/dist/db/cache.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache Database Module
|
|
3
|
+
*
|
|
4
|
+
* Saved queries and results caching functionality.
|
|
5
|
+
*/
|
|
6
|
+
import { getDb } from './connection.js';
|
|
7
|
+
import { createSavedQueriesTable } from './schema.js';
|
|
8
|
+
// Track if saved queries table has been initialized
|
|
9
|
+
let savedQueriesTableInitialized = false;
|
|
10
|
+
/**
|
|
11
|
+
* Ensure the saved queries table exists.
|
|
12
|
+
*/
|
|
13
|
+
function ensureSavedQueriesTable() {
|
|
14
|
+
if (savedQueriesTableInitialized)
|
|
15
|
+
return;
|
|
16
|
+
const database = getDb();
|
|
17
|
+
createSavedQueriesTable(database);
|
|
18
|
+
savedQueriesTableInitialized = true;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the saved queries table.
|
|
22
|
+
* Called automatically when needed.
|
|
23
|
+
*/
|
|
24
|
+
export function initSavedQueriesTable() {
|
|
25
|
+
ensureSavedQueriesTable();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Save a query result to the cache.
|
|
29
|
+
*
|
|
30
|
+
* @param name - Unique name for the saved query
|
|
31
|
+
* @param queryType - Type of query (e.g., 'search', 'coverage', 'gaps')
|
|
32
|
+
* @param queryParams - Parameters used for the query
|
|
33
|
+
* @param result - The result to cache
|
|
34
|
+
* @param ttlMinutes - Optional time-to-live in minutes
|
|
35
|
+
* @returns The generated ID for the saved query
|
|
36
|
+
*/
|
|
37
|
+
export function saveQueryResult(name, queryType, queryParams, result, ttlMinutes) {
|
|
38
|
+
ensureSavedQueriesTable();
|
|
39
|
+
const database = getDb();
|
|
40
|
+
const id = `sq_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
41
|
+
const expiresAt = ttlMinutes
|
|
42
|
+
? new Date(Date.now() + ttlMinutes * 60 * 1000).toISOString()
|
|
43
|
+
: null;
|
|
44
|
+
const stmt = database.prepare(`
|
|
45
|
+
INSERT OR REPLACE INTO saved_queries (id, name, query_type, query_params, result_json, expires_at)
|
|
46
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
47
|
+
`);
|
|
48
|
+
stmt.run(id, name, queryType, JSON.stringify(queryParams), JSON.stringify(result), expiresAt);
|
|
49
|
+
return id;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get a saved query result by name.
|
|
53
|
+
* Returns null if not found or expired.
|
|
54
|
+
*
|
|
55
|
+
* @param name - Name of the saved query
|
|
56
|
+
* @returns The cached result or null
|
|
57
|
+
*/
|
|
58
|
+
export function getSavedQuery(name) {
|
|
59
|
+
ensureSavedQueriesTable();
|
|
60
|
+
const database = getDb();
|
|
61
|
+
const stmt = database.prepare(`
|
|
62
|
+
SELECT result_json, expires_at FROM saved_queries
|
|
63
|
+
WHERE name = ?
|
|
64
|
+
ORDER BY created_at DESC
|
|
65
|
+
LIMIT 1
|
|
66
|
+
`);
|
|
67
|
+
const row = stmt.get(name);
|
|
68
|
+
if (!row)
|
|
69
|
+
return null;
|
|
70
|
+
// Check expiry
|
|
71
|
+
if (row.expires_at && new Date(row.expires_at) < new Date()) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
return JSON.parse(row.result_json);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* List all saved queries, optionally filtered by type.
|
|
78
|
+
*
|
|
79
|
+
* @param queryType - Optional filter by query type
|
|
80
|
+
* @returns Array of saved query metadata
|
|
81
|
+
*/
|
|
82
|
+
export function listSavedQueries(queryType) {
|
|
83
|
+
ensureSavedQueriesTable();
|
|
84
|
+
const database = getDb();
|
|
85
|
+
let sql = 'SELECT id, name, query_type, created_at FROM saved_queries';
|
|
86
|
+
const params = [];
|
|
87
|
+
if (queryType) {
|
|
88
|
+
sql += ' WHERE query_type = ?';
|
|
89
|
+
params.push(queryType);
|
|
90
|
+
}
|
|
91
|
+
sql += ' ORDER BY created_at DESC LIMIT 50';
|
|
92
|
+
return database.prepare(sql).all(...params);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Delete a saved query by name.
|
|
96
|
+
*
|
|
97
|
+
* @param name - Name of the saved query to delete
|
|
98
|
+
* @returns True if a query was deleted, false otherwise
|
|
99
|
+
*/
|
|
100
|
+
export function deleteSavedQuery(name) {
|
|
101
|
+
ensureSavedQueriesTable();
|
|
102
|
+
const database = getDb();
|
|
103
|
+
const result = database.prepare('DELETE FROM saved_queries WHERE name = ?').run(name);
|
|
104
|
+
return result.changes > 0;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Delete all expired saved queries.
|
|
108
|
+
*
|
|
109
|
+
* @returns Number of queries deleted
|
|
110
|
+
*/
|
|
111
|
+
export function cleanupExpiredQueries() {
|
|
112
|
+
ensureSavedQueriesTable();
|
|
113
|
+
const database = getDb();
|
|
114
|
+
const result = database.prepare(`
|
|
115
|
+
DELETE FROM saved_queries
|
|
116
|
+
WHERE expires_at IS NOT NULL AND expires_at < datetime('now')
|
|
117
|
+
`).run();
|
|
118
|
+
return result.changes;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get a saved query result by ID.
|
|
122
|
+
*
|
|
123
|
+
* @param id - ID of the saved query
|
|
124
|
+
* @returns The cached result or null
|
|
125
|
+
*/
|
|
126
|
+
export function getSavedQueryById(id) {
|
|
127
|
+
ensureSavedQueriesTable();
|
|
128
|
+
const database = getDb();
|
|
129
|
+
const stmt = database.prepare(`
|
|
130
|
+
SELECT result_json, expires_at FROM saved_queries
|
|
131
|
+
WHERE id = ?
|
|
132
|
+
`);
|
|
133
|
+
const row = stmt.get(id);
|
|
134
|
+
if (!row)
|
|
135
|
+
return null;
|
|
136
|
+
// Check expiry
|
|
137
|
+
if (row.expires_at && new Date(row.expires_at) < new Date()) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
return JSON.parse(row.result_json);
|
|
141
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Connection Module
|
|
3
|
+
*
|
|
4
|
+
* Manages SQLite connection singleton, path management, and database lifecycle.
|
|
5
|
+
*/
|
|
6
|
+
import Database from 'better-sqlite3';
|
|
7
|
+
/**
|
|
8
|
+
* Get the path to the SQLite database file.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getDbPath(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Get the cache directory path.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getCacheDir(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Initialize and return the database connection singleton.
|
|
17
|
+
* Creates the database file and schema if they don't exist.
|
|
18
|
+
*/
|
|
19
|
+
export declare function initDb(): Database.Database;
|
|
20
|
+
/**
|
|
21
|
+
* Get the database connection, initializing if necessary.
|
|
22
|
+
* This is the primary way other modules should access the database.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getDb(): Database.Database;
|
|
25
|
+
/**
|
|
26
|
+
* Clear all detections from the database.
|
|
27
|
+
*/
|
|
28
|
+
export declare function clearDb(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Force recreation of the database.
|
|
31
|
+
* Useful when schema changes require a fresh start.
|
|
32
|
+
* Handles Windows file locking (EBUSY) with retry logic.
|
|
33
|
+
*/
|
|
34
|
+
export declare function recreateDb(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Check if the database file exists.
|
|
37
|
+
*/
|
|
38
|
+
export declare function dbExists(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Close the database connection.
|
|
41
|
+
*/
|
|
42
|
+
export declare function closeDb(): void;
|