Static Patterns Analyzers vs Semantic Security Discovery in NVIDIA SkillSpector
Static patterns analyzers perform deterministic, rule-based code scanning for concrete vulnerabilities, while semantic_security_discovery uses LLM reasoning to infer higher-level security concerns from skill intent.
The NVIDIA SkillSpector repository provides two fundamentally different security analysis families within its graph-based meta-analyzer pipeline. Understanding the distinction between static_patterns analyzers and semantic_security_discovery is essential for configuring effective security scanning of AI agent skills.
Core Architectural Differences
Static Patterns: Deterministic Rule-Based Detection
Static patterns analyzers operate through pure static code inspection without external AI services. In src/skillspector/nodes/analyzers/static_runner.py, the StaticRunner class loads collections of regular-expression and YARA-style rules from modules like src/skillspector/nodes/analyzers/pattern_defaults.py. These analyzers scan the abstract syntax tree (AST) or raw source files for exact pattern matches.
The detection logic is entirely deterministic. For example, src/skillspector/nodes/analyzers/static_patterns_privilege_escalation.py defines YARA-compatible strings that match against specific code signatures like hard-coded secrets or supply-chain misuse. Each analyzer targets a specific vulnerability class—prompt injection, tool misuse, memory poisoning, or privilege escalation—by iterating over rule registries and applying them to the AST constructed by the resolve_input node.
Semantic Security Discovery: LLM-Powered Inference
The SemanticSecurityDiscovery node in src/skillspector/nodes/analyzers/semantic_security_discovery.py takes a fundamentally different approach by reasoning over the semantics of skill code using a Large Language Model (LLM). This analyzer first calls build_context to gather a concise description of the skill—including its entry-point, imports, doc-strings, and inferred intent—then forwards that context to an LLM provider via llm_utils.call_llm.
The LLM provider implementation (found in providers/openai/provider.py or providers/anthropic/provider.py) processes the request and returns a JSON response that is parsed into Issue objects. These issues represent higher-level security concerns such as unintentional data exfiltration, intent clashes with least-privilege principles, or privilege escalation via indirect API calls.
Performance and Reliability Trade-offs
Static patterns analyzers deliver fast, predictable performance that scales linearly with file size and rule count. Results remain reproducible across runs, offering high precision for well-defined patterns but limited recall for issues not covered by the rule set.
Semantic security discovery requires network calls to LLM endpoints (such as OpenAI's gpt-4-turbo), making execution slower and results potentially variable with model updates or temperature settings. This approach achieves higher recall for subtle, context-dependent threats but exhibits lower precision due to the risk of LLM hallucination or over-generalization.
Configuration and Customization
Modifying Static Pattern Rules
Rules for static analysis live in individual static_patterns_*.py modules under src/skillspector/nodes/analyzers/. Adding new detection capabilities requires editing the corresponding Python list or YARA file without modifying the core engine. The MetaAnalyzer in src/skillspector/nodes/meta_analyzer.py automatically discovers and loads these patterns through the registry system.
Customizing Semantic Discovery
The discovery prompt template is embedded directly in src/skillspector/nodes/analyzers/semantic_security_discovery.py. Customization occurs by changing the system prompt or swapping the LLM provider in the provider configuration files. The base class LLMAnalyzerBase in src/skillspector/llm_analyzer_base.py handles the request/response plumbing, allowing subclasses to focus on context preparation and result parsing.
Code Examples
Running Static Pattern Analysis
Execute a privilege-escalation scan from the command line interface:
skill-spector run \
--skill-path path/to/skill \
--analyzer static_patterns_privilege_escalation
The CLI (src/skillspector/cli.py) forwards this request to MetaAnalyzer, which loads the specific analyzer module and prints any matching issues found in the skill's AST.
Invoking Semantic Security Discovery
Programmatically run the LLM-based analyzer:
from skillspector.graph import SkillGraph
from skillspector.nodes.analyzers.semantic_security_discovery import SemanticSecurityDiscovery
# Build the graph for a local skill
graph = SkillGraph.from_path("path/to/skill")
# Run only the semantic discovery node
discovery = SemanticSecurityDiscovery(graph)
issues = discovery.run()
for issue in issues:
print(issue.title, "→", issue.description)
This call internally performs the LLM request and returns a list of Issue objects representing discovered security concerns.
Adding Custom Static Rules
Extend detection capabilities by editing src/skillspector/nodes/analyzers/static_patterns_privilege_escalation.py:
# New pattern that catches usage of `os.system` with elevated privileges
NEW_PATTERN = r'os\.system\(["\'].*sudo.*["\']\)'
PATTERNS.append(NEW_PATTERN)
Re-run the analyzer; the new rule matches immediately without requiring changes to the runner infrastructure.
Summary
- Static patterns analyzers use deterministic, rule-based AST scanning in
src/skillspector/nodes/analyzers/to detect concrete vulnerabilities like secret leakage and supply-chain poisoning. - Semantic security discovery leverages LLM reasoning through
src/skillspector/nodes/analyzers/semantic_security_discovery.pyto identify subtle, context-dependent security concerns. - Static analysis offers high precision and reproducibility with linear performance scaling, while semantic discovery provides broader coverage with variable latency dependent on network calls.
- Both analyzer families ultimately produce
Issueobjects consumed by theReportnode (src/skillspector/nodes/report.py) and exportable as SARIF format.
Frequently Asked Questions
What is the main difference between static_patterns analyzers and semantic_security_discovery?
Static patterns analyzers perform deterministic scans using regex and YARA-style rules against the AST to find concrete code patterns, while semantic_security_discovery sends skill context to an LLM to infer higher-level security concerns. The former operates entirely offline with predictable results, whereas the latter requires external AI services and interprets code intent rather than matching literal patterns.
When should I use static_patterns analyzers instead of semantic_security_discovery?
Use static patterns analyzers when you need fast, reproducible detection of known vulnerability signatures such as hard-coded credentials, unsafe imports, or prompt injection vectors. Choose semantic security discovery when assessing complex skills where context-dependent risks—like implicit data exfiltration or privilege escalation through indirect API calls—require understanding the skill's intended behavior beyond literal code patterns.
How do I configure the LLM provider for semantic_security_discovery?
Configure the LLM provider by modifying providers/openai/provider.py or providers/anthropic/provider.py and adjusting the system prompt in src/skillspector/nodes/analyzers/semantic_security_discovery.py. The LLMAnalyzerBase class handles the underlying request plumbing, allowing you to swap models or providers without changing the core discovery logic.
Can I extend static_patterns analyzers with custom rules?
Yes, custom rules are added by editing the specific pattern module files such as src/skillspector/nodes/analyzers/static_patterns_privilege_escalation.py. Append new regex patterns to the module's pattern list; the StaticRunner automatically picks up these changes through the pattern registry (src/skillspector/nodes/analyzers/pattern_defaults.py) without requiring code modifications to the execution engine.
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 →