How to Add Custom YARA Rules to SkillSpector for Malware and Hack-Tool Detection

SkillSpector supports custom YARA rule directories via the --yara-rules-dir flag, automatically merging user-supplied .yar files with built-in rules for static analysis of skill packages.

NVIDIA's SkillSpector ships with a built-in YARA analyzer located in src/skillspector/yara_rules/ that detects malware, hack tools, webshells, and cryptominers. You can extend this detection capability by supplying your own rule files without modifying the core repository. This guide covers the exact CLI workflow, metadata schema, and source code implementation details you need to integrate custom YARA rules.

How the YARA Analyzer Works

The YARA analyzer node (static_yara.node) executes as part of the SkillSpector analysis pipeline. It compiles rule sets once, caches them based on a content hash (_content_hash), and scans every artifact extracted from the skill package—including source files and binaries.

Built-in Rules Location

SkillSpector distributes a curated rule bundle in src/skillspector/yara_rules/. These rules cover common threats like webshells, malware families, and exploit patterns. The analyzer loads these automatically on every run.

Rule Loading and Compilation

When the analyzer executes, it invokes _load_rules(extra_dir) in src/skillspector/nodes/analyzers/static_yara.py. This method compiles both the built-in rules and any user-supplied directory into a single yara.Rules object. The compilation step includes generating a content hash for caching, ensuring that repeated scans of identical rule sets execute quickly.

State Management

The CLI parses the --yara-rules-dir argument in src/skillspector/cli.py and stores the path in the global analysis state under the key yara_rules_dir (defined in src/skillspector/state.py). Downstream nodes access this path to locate custom rules on disk.

Step-by-Step Guide to Adding Custom YARA Rules

1. Create Your Rule Directory

Create a directory anywhere on your host machine to store .yar or .yara files:

mkdir -p /home/user/custom_yara/extra_rules

SkillSpector recursively scans this directory, so you can organize rules into subdirectories.

2. Author YARA Rules with SkillSpector Metadata

Each rule file must contain at least one valid YARA rule. Include a meta section with specific keys to control how SkillSpector categorizes and reports findings:

  • category: Maps to the rule ID prefix and severity (e.g., malware, hack_tool, webshell, cryptominer, exploit). The _CATEGORY_MAP_ in static_yara.py defines the default mappings.
  • severity: Sets the SARIF severity level (e.g., CRITICAL, HIGH, MEDIUM, LOW).
  • confidence: Float value between 0 and 1 representing detection confidence.
  • description: Human-readable text included in the finding message.

Example custom rule (my_malware.yar):

rule MyMalware
{
    meta:
        category = "malware"
        severity = "CRITICAL"
        confidence = 0.9
        description = "Detects known malicious payload pattern"

    strings:
        $a = "malicious_string"
        $b = { 6A 40 68 ?? ?? ?? ?? 6A 00 6A 01 6A 02 6A 03 }

    condition:
        any of ($a, $b)
}

3. Run SkillSpector with the Custom Directory

Pass the absolute path to your rules directory using the --yara-rules-dir flag:

skill-spector scan path/to/skill.zip \
    --yara-rules-dir /home/user/custom_yara \
    --format json \
    --output findings.json

The analyzer merges your rules with the built-in set, compiles them, and scans all extracted artifacts.

Inspecting YARA Findings in Output

For every YARA match, the analyzer creates an AnalyzerFinding object. The _build_message method in static_yara.py constructs the message string incorporating the rule name, description, and namespace. This finding is then transformed into SARIF format.

Example JSON output for a custom rule match:

{
  "rule_id": "YR1",
  "message": "YARA rule 'MyMalware': Detects known malicious payload pattern",
  "severity": "CRITICAL",
  "location": {
    "file": "src/main.py",
    "startLine": 42
  },
  "confidence": 0.9,
  "tags": ["yara_match"],
  "context": "... snippet of surrounding code ...",
  "matchedText": "malicious_string"
}

Programmatic Access to Rule Compilation

You can manually load and inspect custom rules using the internal API—useful for debugging rule syntax before running a full scan:

from pathlib import Path
from skillspector.nodes.analyzers import static_yara

# Load rules manually

custom_dir = Path("/home/user/custom_yara")
compiled = static_yara._load_rules(custom_dir)  # returns yara.Rules or None

if compiled:
    print(f"Compiled {len(compiled.rules)} rules")
    for rule in compiled.rules:
        print(f"  - {rule.identifier}")

Summary

  • SkillSpector automatically loads built-in YARA rules from src/skillspector/yara_rules/ and merges them with user-supplied directories.
  • Use the --yara-rules-dir flag to specify your custom rule path; the CLI stores this in state.py under yara_rules_dir.
  • Rule files must use .yar or .yara extensions and include meta keys (category, severity, confidence, description) for proper categorization.
  • The static_yara.py node compiles rules via _load_rules(), caches them using _content_hash, and generates SARIF findings via _build_message().
  • Custom and built-in rules are compiled together once per run, ensuring optimal performance while maintaining detection coverage.

Frequently Asked Questions

What file extensions does SkillSpector recognize for YARA rules?

SkillSpector recognizes files ending in .yar or .yara. The _load_rules() method in static_yara.py scans the specified directory recursively and compiles any files matching these extensions.

How does SkillSpector resolve conflicts between built-in and custom rules?

SkillSpector merges rule sets before compilation. If duplicate rule identifiers exist, the YARA compiler will raise an error. The analyzer loads built-in rules first, then appends custom rules from the directory specified in --yara-rules-dir, compiling them into a single cached rules object.

What metadata keys are required for proper severity mapping?

While YARA rules function without metadata, SkillSpector specifically looks for category, severity, confidence, and description in the meta section. The category key determines the default rule ID prefix and severity mapping via _CATEGORY_MAP_ in static_yara.py.

Where does SkillSpector cache compiled YARA rules?

The analyzer caches compiled rules based on a content hash (_content_hash) calculated from the combined rule text. This cache persists for the duration of the analysis run, ensuring that repeated scans of the same skill package with unchanged rules skip recompilation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →