How to Manage False Positives with SkillSpector Baseline Suppression: A Team Guide
SkillSpector baseline suppression filters false positives using YAML-based rules for glob patterns and exact SHA-256 fingerprints, enabling teams to maintain clean CI scans across shared repositories.
NVIDIA's SkillSpector open-source security scanner uses a baseline file to exclude findings that teams classify as non-vulnerabilities. Understanding how to configure this suppression system allows development teams to eliminate noise while preserving critical security signals across collaborative workflows.
How Baseline Suppression Works in SkillSpector
SkillSpector implements a dual-mechanism approach in src/skillspector/suppression.py to distinguish between acceptable and actionable findings. The system evaluates every finding against rules (pattern-based) and fingerprints (exact-match) to determine suppression status.
Glob-Based Rules for Systematic Patterns
The rules array contains human-authored patterns that match a finding's id, path, and/or message. A rule suppresses a finding only when all specified fields satisfy the glob pattern. The _match_glob function normalizes ** to * and executes case-insensitive fnmatch matching (see module docstring lines 47-50). An empty rule never matches, preventing accidental catch-all suppressions.
When to use: Ideal for systematic false positives, such as excluding rule "SQP-1" globally or filtering specific paths like *deploy-topology*/SKILL.md.
Exact Fingerprints for Specific Findings
The fingerprints array stores stable SHA-256 hashes generated by finding_fingerprint() (lines 85-103). This hash incorporates the rule ID, file path, line range, and message content. Only new, unseen fingerprints survive subsequent scans, making this mechanism perfect for incremental CI workflows where teams want to freeze the current finding set.
When to use: Best for "accept-as-is" findings where the underlying code won't change, ensuring any modification resurfaces the finding for re-evaluation.
Core Implementation Details
In src/skillspector/suppression.py, the Baseline class orchestrates suppression logic:
SuppressionRule.matches()evaluates whether a finding satisfies all rule criteria (rule_id, path, message)Baseline.reason_for()(lines 50-58) returns the suppression reason for matched findingspartition_findings()(lines 27-46) splits findings into kept and suppressed subsetsload_baseline()(lines 9-24) parses the YAML/JSON baseline file
The report node in src/skillspector/nodes/report.py (lines 408-410) excludes suppressed findings from SARIF output and risk score calculations.
Managing False Positives Across Team Scans
Establishing a shared suppression policy requires version-controlling your baseline and adhering to granular matching strategies.
Step-by-Step Baseline Creation Workflow
-
Run an initial scan without baselines to capture all current findings.
-
Generate a baseline file from existing findings:
skillspector baseline <skill-dir> --no-llm --output baseline.yamlThe CLI in
src/skillspector/cli.pyinvokesbuild_baseline_dict()(lines 49-66) anddump_baseline()(lines 69-79) to fingerprint every finding. -
Refine with human-authored rules by editing
baseline.yamlto address recurring false positives:version: 1 rules: - id: "SQP-1" reason: "Trigger-phrase nit, not a vulnerability" - id: "SSD-2" path: "*deploy-topology*/SKILL.md" message: "*run the exploit*" reason: "False positive: test-workflow phrase" fingerprints: - hash: "sha256:1a2b3c4d5e6f7081" rule_id: "SDI-2" file: "baas-build-analysis/SKILL.md" reason: "Accepted 2026-06-19 — first-party env detection" -
Commit the baseline to your repository (e.g.,
skill-configs/baseline.yaml) so all team members and CI pipelines use identical suppression logic. -
Execute filtered scans using the shared baseline:
skillspector scan <skill-dir> --baseline baseline.yaml
Team Collaboration Best Practices
- Commit the baseline to version control to ensure every CI run and developer scan applies the same policy.
- Keep rules specific by including
pathormessageconstraints to avoid unintentionally silencing legitimate vulnerabilities. - Prefer fingerprints for one-off acceptances since any code or message change generates a new fingerprint, forcing re-evaluation.
- Automate baseline regeneration in CI steps that run
skillspector baselineon clean scans, updating the file only after explicit team review. - Monitor suppression statistics via the report node summary (
Suppressed by baseline: Nat line 408) to track filtering volume.
Programmatic API and CLI Usage
SkillSpector exposes Python APIs for custom suppression workflows:
# Load and query a baseline
from skillspector.suppression import load_baseline
from skillspector.models import Finding
baseline = load_baseline("baseline.yaml")
f = Finding(rule_id="SQP-1", file="my/skill/SKILL.md", message="Trigger phrase")
reason = baseline.reason_for(f) # Returns: "Trigger-phrase nit, not a vulnerability"
# Programmatically create baselines
from skillspector.suppression import build_baseline_dict, dump_baseline
baseline_dict = build_baseline_dict([f], reason="Accepted in CI")
dump_baseline(baseline_dict, "baseline.yaml")
# Complete CLI round-trip
skillspector baseline my_skill --no-llm --output baseline.yaml
skillspector scan my_skill --baseline baseline.yaml
Summary
- SkillSpector uses two complementary suppression mechanisms: glob-based rules for patterns and SHA-256 fingerprints for exact matches.
- The core logic resides in
src/skillspector/suppression.py, withpartition_findings()andBaseline.reason_for()handling the filtering decisions. - Teams should commit baselines to version control and use specific rules to avoid over-suppression.
- Fingerprints provide immutable acceptance of specific findings, while rules handle systematic false positive categories.
- Suppressed findings are excluded from SARIF reports and risk scores according to
src/skillspector/nodes/report.pylogic.
Frequently Asked Questions
What is the difference between rules and fingerprints in SkillSpector?
Rules use glob patterns to match multiple findings based on ID, file path, or message content, making them ideal for systematic false positives. Fingerprints store exact SHA-256 hashes of specific findings (generated from rule ID, file, line range, and message), ensuring only identical findings are suppressed. Fingerprints automatically surface findings when underlying code changes, while rules persist until manually removed.
How do I create a baseline file for my team?
Run skillspector baseline <skill-dir> --no-llm --output baseline.yaml to generate a file containing fingerprints of all current findings. Edit this file to add human-authored rules for recurring false positives, then commit it to your repository. Future scans using skillspector scan <skill-dir> --baseline baseline.yaml will filter matched findings from reports and risk scores.
Why are my suppressed findings still appearing in the scan?
Verify that your baseline file path is correct and accessible to the CLI. Check that rule glob patterns use correct syntax (* matches across path separators, ** normalizes to *). For fingerprint-based suppressions, any change to the finding's rule ID, file path, line numbers, or message text generates a new SHA-256 hash, causing the finding to resurface for re-evaluation.
How does SkillSpector calculate finding fingerprints?
The finding_fingerprint() function in src/skillspector/suppression.py (lines 85-103) computes a deterministic SHA-256 hash from the finding's rule ID, absolute file path, line range, and message content. This ensures that any modification to the underlying code or LLM-generated message invalidates the fingerprint, preventing stale suppressions from masking new vulnerabilities.
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 →