npm package: @modular-intelligence/detection-rules
Description: MCP server for Sigma & YARA rule validation, conversion, and scanning
Latest version: 1.0.2

# Detection Rules MCP Server

An MCP server for validating, converting, and scanning detection rules using Sigma and YARA formats. Enables Claude and other MCP clients to work with security detection rules for SIEM platforms, threat hunting, and malware analysis.

## Features

- **Sigma Rule Support**: Validate Sigma rules and convert them to multiple SIEM backends (Splunk, Elasticsearch, QRadar, etc.)
- **YARA Rule Support**: Validate YARA rules and scan files/directories for malware patterns
- **Multi-Backend Conversion**: Support for numerous conversion targets with optional processing pipelines
- **Real-time Scanning**: Scan files and directories with customizable timeouts
- **Security-First**: File path validation, rule content size limits, and backend name sanitization
- **Error Handling**: Detailed validation errors and warnings with rule metadata extraction

## Tools

| Tool | Purpose |
|------|---------|
| `sigma_validate` | Validate Sigma rule YAML for syntax and semantic correctness |
| `sigma_convert` | Convert Sigma rules to target SIEM query languages (SPL, KQL, etc.) |
| `sigma_list_backends` | List all available Sigma conversion backends |
| `yara_validate` | Compile and validate YARA rules for syntax errors |
| `yara_scan` | Scan files or directories with YARA rules |

### sigma_validate

Validates a Sigma rule YAML file for correctness using the sigma-cli.

**Input Schema:**
```json
{
  "rule": "string (Sigma rule YAML content, min 10 chars)"
}
```

**Output:**
```json
{
  "valid": true,
  "errors": [],
  "warnings": [],
  "rule_title": "File Access via Uncommon Extension",
  "rule_level": "medium",
  "rule_status": "test"
}
```

**Example Usage:**

```python
# Input
{
  "rule": """
title: Suspicious Process Creation with Network Activity
id: 12345678-1234-1234-1234-123456789012
status: test
description: Detects unusual process creation followed by network connection
logsource:
  product: windows
  service: sysmon
detection:
  process_creation:
    EventID: 1
    Image|endswith:
      - 'powershell.exe'
      - 'cmd.exe'
  network_connection:
    EventID: 3
    DestinationPort:
      - 445
      - 139
  filter:
    Image|contains: 'system32'
  condition: process_creation and network_connection and not filter
level: high
"""
}

# Output
{
  "valid": true,
  "errors": [],
  "warnings": ["Field 'description' should use proper formatting"],
  "rule_title": "Suspicious Process Creation with Network Activity",
  "rule_level": "high",
  "rule_status": "test"
}
```

### sigma_convert

Converts a Sigma rule to a target SIEM backend query language. Supports optional processing pipelines for backend-specific transformations.

**Input Schema:**
```json
{
  "rule": "string (Sigma rule YAML content, min 10 chars)",
  "backend": "string (Target backend name: splunk, elasticsearch, qradar, etc.)",
  "pipeline": "string (optional, Processing pipeline name e.g., sysmon, windows)"
}
```

**Output:**
```json
{
  "backend": "splunk",
  "pipeline": "sysmon",
  "converted_query": "index=main Image=*powershell.exe OR Image=*cmd.exe (DestinationPort=445 OR DestinationPort=139) NOT Image=*system32*",
  "warnings": []
}
```

**Example Usage:**

Converting a Sigma rule to Splunk SPL:

```python
# Input
{
  "rule": """
title: Process Creation with Command Line Args
id: 11111111-2222-3333-4444-555555555555
logsource:
  product: windows
  service: sysmon
detection:
  selection:
    EventID: 1
    Image|endswith: 'powershell.exe'
    CommandLine|contains:
      - 'DownloadString'
      - 'IEX'
      - 'Invoke-WebRequest'
  condition: selection
level: high
""",
  "backend": "splunk",
  "pipeline": "sysmon"
}

# Output
{
  "backend": "splunk",
  "pipeline": "sysmon",
  "converted_query": "index=main EventID=1 Image=*powershell.exe (CommandLine=*DownloadString* OR CommandLine=*IEX* OR CommandLine=*Invoke-WebRequest*)",
  "warnings": []
}
```

### sigma_list_backends

Lists all available Sigma conversion backends supported by the sigma-cli installation.

**Input Schema:**
```json
{}
```

**Output:**
```json
{
  "backends": [
    {
      "name": "splunk",
      "description": "Splunk Processing Language (SPL)"
    },
    {
      "name": "elasticsearch",
      "description": "Elasticsearch Query Language (KQL)"
    },
    {
      "name": "qradar",
      "description": "IBM QRadar Query Language"
    },
    {
      "name": "sentinel",
      "description": "Microsoft Azure Sentinel KQL"
    },
    {
      "name": "graylog",
      "description": "Graylog Query Language"
    }
  ]
}
```

**Example Usage:**

```python
# Input
{}

# Output (sample)
{
  "backends": [
    {"name": "splunk", "description": "Splunk Processing Language"},
    {"name": "elasticsearch", "description": "Elasticsearch Query Language"},
    {"name": "qradar", "description": "IBM QRadar"},
    {"name": "sentinel", "description": "Microsoft Sentinel KQL"},
    {"name": "windows-defender", "description": "Windows Defender Advanced Threat Protection"},
    {"name": "crowdstrike", "description": "CrowdStrike Falcon"}
  ]
}
```

### yara_validate

Compiles and validates a YARA rule for syntax errors. Extracts rule names from the provided rule content.

**Input Schema:**
```json
{
  "rule": "string (YARA rule content, min 10 chars)"
}
```

**Output:**
```json
{
  "valid": true,
  "errors": [],
  "rule_names": ["malware_strings", "suspicious_imports"]
}
```

**Example Usage:**

```python
# Input
{
  "rule": """
rule malware_strings {
    meta:
        description = "Detects common malware strings"
        severity = "high"
    strings:
        $a = "CreateRemoteThread"
        $b = "WinExec"
        $c = /kernel32\.dll/i
    condition:
        2 of them
}

rule suspicious_imports {
    meta:
        description = "Detects suspicious API imports"
    strings:
        $import1 = "GetProcAddress"
        $import2 = "LoadLibrary"
    condition:
        all of them
}
"""
}

# Output
{
  "valid": true,
  "errors": [],
  "rule_names": ["malware_strings", "suspicious_imports"]
}
```

### yara_scan

Scans a file or directory with a YARA rule. Returns all matching rules and the specific strings that matched.

**Input Schema:**
```json
{
  "rule": "string (YARA rule content, min 10 chars)",
  "target": "string (Absolute file or directory path)",
  "recursive": "boolean (optional, default: false, scan directories recursively)",
  "timeout": "integer (optional, default: 60, range: 5-300 seconds)"
}
```

**Output:**
```json
{
  "target": "/path/to/file",
  "match_count": 2,
  "matches": [
    {
      "rule": "malware_strings",
      "file": "/path/to/file.exe",
      "strings": [
        {
          "identifier": "$a",
          "offset": "0x1234",
          "data": "CreateRemoteThread"
        },
        {
          "identifier": "$b",
          "offset": "0x5678",
          "data": "WinExec"
        }
      ]
    }
  ],
  "scan_time_ms": 245
}
```

**Example Usage:**

Scanning a file for malware patterns:

```python
# Input
{
  "rule": """
rule ransomware_indicators {
    meta:
        description = "Detects common ransomware patterns"
        author = "Security Team"
    strings:
        $bitcoin_wallet = /bitcoin:\/\/[a-zA-Z0-9]{26,35}/
        $file_operations = "SetFilePointer"
        $registry_run = "Software\\\\Microsoft\\\\Windows\\\\Run"
        $mutex = {4D 5A 90 00} // MZ header + suspicious pattern
    condition:
        3 of them
}
""",
  "target": "/home/user/Downloads/suspicious.exe",
  "recursive": false,
  "timeout": 30
}

# Output
{
  "target": "/home/user/Downloads/suspicious.exe",
  "match_count": 1,
  "matches": [
    {
      "rule": "ransomware_indicators",
      "file": "/home/user/Downloads/suspicious.exe",
      "strings": [
        {
          "identifier": "$file_operations",
          "offset": "0x4a2f",
          "data": "SetFilePointer"
        },
        {
          "identifier": "$registry_run",
          "offset": "0x7c1d",
          "data": "Software\\Microsoft\\Windows\\Run"
        },
        {
          "identifier": "$mutex",
          "offset": "0x0400",
          "data": "MZ"
        }
      ]
    }
  ],
  "scan_time_ms": 523
}
```

Scanning a directory recursively:

```python
# Input
{
  "rule": """
rule webshell_patterns {
    strings:
        $php = "<?php"
        $shell_var = "$_GET"
        $system_call = "system("
    condition:
        2 of them
}
""",
  "target": "/var/www/html",
  "recursive": true,
  "timeout": 120
}

# Output
{
  "target": "/var/www/html",
  "match_count": 3,
  "matches": [
    {
      "rule": "webshell_patterns",
      "file": "/var/www/html/uploads/shell.php",
      "strings": [
        {"identifier": "$php", "offset": "0x0", "data": "<?php"},
        {"identifier": "$shell_var", "offset": "0x45", "data": "$_GET"},
        {"identifier": "$system_call", "offset": "0x89", "data": "system("}
      ]
    },
    {
      "rule": "webshell_patterns",
      "file": "/var/www/html/admin/upload.php",
      "strings": [
        {"identifier": "$php", "offset": "0x0", "data": "<?php"},
        {"identifier": "$system_call", "offset": "0x120", "data": "system("}
      ]
    },
    {
      "rule": "webshell_patterns",
      "file": "/var/www/html/api/handler.php",
      "strings": [
        {"identifier": "$php", "offset": "0x0", "data": "<?php"},
        {"identifier": "$shell_var", "offset": "0x78", "data": "$_GET"}
      ]
    }
  ],
  "scan_time_ms": 1847
}
```

## Prerequisites

The server requires two command-line tools to be installed and available in your PATH:

### sigma-cli

The Sigma rule toolkit for validation and conversion.

**Installation:**
```bash
pip install sigma-cli
```

**What it does:**
- Validates Sigma rule YAML syntax and semantics
- Converts Sigma rules to multiple SIEM query languages
- Provides rule checking and linting capabilities
- Supports custom processing pipelines

**Verify installation:**
```bash
sigma --version
sigma list backends
```

### YARA

A tool for malware research and detection using pattern matching.

**Installation (macOS):**
```bash
brew install yara
```

**Installation (Linux - Ubuntu/Debian):**
```bash
sudo apt-get install yara
```

**Installation (Linux - RHEL/CentOS):**
```bash
sudo yum install yara
```

**Installation (from source):**
```bash
git clone https://github.com/VirusTotal/yara.git
cd yara
./bootstrap.sh
./configure
make
sudo make install
```

**What it does:**
- Compiles and validates YARA rule syntax
- Scans files and directories for pattern matches
- Provides detailed match output with offsets and matched strings
- Supports recursive directory scanning

**Verify installation:**
```bash
yara --version
yarac --help
```

## Installation

### Prerequisites

- Node.js 18+ or Bun runtime
- npm or bun package manager
- sigma-cli (Python)
- YARA

### Setup with Bun

1. Clone or download the server directory:
```bash
cd /path/to/detection-rules
```

2. Install dependencies:
```bash
bun install
```

3. Build the server:
```bash
bun run build
```

This produces a compiled bundle in the `dist/` directory.

### Setup with npm

If you prefer npm instead of bun:

```bash
npm install
npm run build
```

## Usage

### Running the Server

With Bun:
```bash
bun run src/index.ts
```

Or use the built distribution:
```bash
bun dist/index.js
```

With Node.js:
```bash
node dist/index.js
```

The server runs in stdio mode and is designed to be invoked by MCP clients (Claude, etc.) via configuration.

### Claude Desktop Configuration

Add the following to your Claude Desktop configuration file:

**Location:** `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "detection-rules": {
      "command": "/usr/local/bin/bun",
      "args": [
        "/path/to/detection-rules/src/index.ts"
      ],
      "disabled": false
    }
  }
}
```

Or if using the built distribution:

```json
{
  "mcpServers": {
    "detection-rules": {
      "command": "bun",
      "args": [
        "/path/to/detection-rules/dist/index.js"
      ],
      "disabled": false
    }
  }
}
```

For Node.js users:

```json
{
  "mcpServers": {
    "detection-rules": {
      "command": "node",
      "args": [
        "/path/to/detection-rules/dist/index.js"
      ],
      "disabled": false
    }
  }
}
```

### Claude Code MCP Settings

If using Claude Code or other MCP clients, configure as follows:

```json
{
  "mcpServers": {
    "detection-rules": {
      "command": "bun",
      "args": [
        "/path/to/detection-rules/src/index.ts"
      ]
    }
  }
}
```

### Example Queries in Claude

Once configured, you can ask Claude:

"Validate this Sigma rule and convert it to Splunk SPL"

"Scan /home/user/malware with this YARA rule"

"List all available Sigma conversion backends"

"Check if this YARA rule compiles without errors"

## Security

### File Path Validation

The server implements strict file path validation:

- **Blocked Paths**: Access to system-critical paths is prevented:
  - `/etc/shadow` and `/etc/passwd`
  - `/proc` and `/sys`
  - `/dev`

- **Path Resolution**: Paths are normalized and resolved to absolute paths to prevent directory traversal attacks

- **Existence Checking**: Paths must exist before scanning

Example:
```python
# This will be rejected
target: "/etc/passwd"  # Error: Access not allowed

# This will be accepted
target: "/home/user/suspicious_file.exe"
```

### Rule Content Size Limits

Both Sigma and YARA rules are subject to size validation:

- **Maximum Size**: 100 KB per rule
- **Minimum Size**: 10 characters (must contain meaningful content)

Example:
```python
# This will be rejected (too small)
rule: "rule test"  # Error: Content too small

# This will be rejected (too large)
rule: "..." # (100KB+ content) Error: Rule too large
```

### Backend Name Sanitization

Backend names are validated using strict alphanumeric rules:

- **Allowed Characters**: Letters (a-z, A-Z), numbers (0-9), hyphens (-), underscores (_)
- **Validation**: Prevents injection attacks and invalid backend names

Example:
```python
# Valid backend names
backend: "splunk"
backend: "elasticsearch"
backend: "windows-defender"
backend: "custom_backend"

# Invalid backend names (will be rejected)
backend: "splunk; rm -rf /"  # Error: Invalid characters
backend: "$(malicious)"       # Error: Invalid characters
```

### Command Execution

- **CLI tools** are executed with proper sandboxing using Node.js `execFile`
- **30-second default timeout** for all commands (configurable for scans)
- **5 MB output buffer** limit to prevent memory exhaustion
- **Temporary file cleanup** ensures no sensitive data persists

## Troubleshooting

### sigma CLI not found

If you see "sigma CLI not found. Install: pip install sigma-cli":

```bash
# Ensure Python and pip are installed
python3 --version
pip3 --version

# Install sigma-cli
pip3 install sigma-cli

# Verify installation
sigma --version
```

### YARA not found

If you see "yara not found. Install: brew install yara":

```bash
# macOS
brew install yara

# Linux
sudo apt-get install yara  # Ubuntu/Debian
sudo yum install yara      # RHEL/CentOS

# Verify installation
yara --version
yarac --help
```

### Timeout errors

If scans are timing out:

- Increase the `timeout` parameter in `yara_scan` (range: 5-300 seconds)
- For large directories, use `recursive: true` with longer timeouts
- Check system resources; scanning very large files may require optimization

### Rule validation errors

If rules fail validation:

- Check YAML/rule syntax carefully
- Review warning messages for hints
- Use `sigma_list_backends` to verify backend names
- For YARA rules, ensure proper syntax for meta, strings, and condition blocks

## Development

### Project Structure

```
src/
  index.ts              # MCP server initialization and tool registration
  schemas.ts            # Zod validation schemas
  security.ts           # Path and content validation
  types.ts              # TypeScript interfaces
  cli-executor.ts       # Command execution utilities
  tools/
    sigma-validate.ts   # Sigma rule validation
    sigma-convert.ts    # Sigma rule conversion
    sigma-list-backends.ts  # Backend listing
    yara-validate.ts    # YARA rule validation
    yara-scan.ts        # YARA file scanning
dist/
  index.js              # Compiled output (generated by build)
```

### Adding New Tools

To add a new tool:

1. Create a new file in `src/tools/` with the tool name
2. Export a schema object (e.g., `toolNameSchema`) using Zod
3. Export an async function with the tool logic
4. Import and register in `src/index.ts` using `server.tool()`

Example:

```typescript
// src/tools/custom-tool.ts
import { z } from "zod";

export const customToolSchema = z.object({
  input: z.string().describe("Input parameter"),
});

type CustomToolInput = z.infer<typeof customToolSchema>;

export async function customTool(input: CustomToolInput) {
  return { result: "output" };
}
```

### Building and Testing

```bash
# Build
bun run build

# Run the server
bun run src/index.ts

# Or run tests (if added)
bun test
```

## License

MIT

## Contributing

Contributions are welcome! Please ensure:

- All tools have proper input validation
- Security checks are in place for file operations
- Error messages are clear and helpful
- Code follows existing style conventions