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_instatic_yara.pydefines 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-dirflag to specify your custom rule path; the CLI stores this instate.pyunderyara_rules_dir. - Rule files must use
.yaror.yaraextensions and includemetakeys (category,severity,confidence,description) for proper categorization. - The
static_yara.pynode 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →