Skip to content
Cisco AI Defense logo
CiscoAI Security

Scan Policies — Skill Scanner

Scan Policies

Scan policies define scanner behavior without code changes. Start with a built-in preset, then override only what your organization needs.


Which Preset Should I Use?

Recommended Settings answers this by goal, with measured numbers. Every recommended setup runs the LLM judge (--use-llm). In short:

Scanning...Use
Your own skills, locally, in pre-commit or in CIlow-noise with the LLM judge
Third-party skills, highest F1balanced (default) with the LLM judge; block HIGH, review MEDIUM
Third-party skills, lowest false-positive ratequiet with the LLM judge, never without it
Audits and threat huntingstrict with the LLM judge; read everything, never a gate

permissive turns CEL and correlation off. It has not been measured as a gate, so for fewer false positives prefer low-noise.


Built-In Presets

PresetCEL / correlationPostureTypical Use
strictshadow / onMaximum sensitivityUntrusted content, compliance audits, security reviews
balancedshadow / onDefault blendGeneral CI usage, day-to-day development scanning
permissiveoff / offLower noiseTrusted internal workflows, known-safe skill directories
low-noiseshadow / onBalanced, fewer harmless flagsYour own skills, and the judge with a smaller queue: 11 rules reported at LOW; LLM findings the model rates low-confidence capped at LOW
quietshadow / onFewest flagsThird-party skills with the judge, when review capacity is the constraint: 19 rules reported at LOW, and LLM low-confidence and contextual-risk findings capped at LOW. Not without the judge
skill-scanner scan ./my-skill --use-llm --policy balanced
skill-scanner scan ./my-skill --use-llm --policy low-noise
skill-scanner scan ./my-skill --use-llm --policy quiet
skill-scanner scan ./my-skill --use-llm --policy strict

Override the selected policy for one invocation with --cel-mode off|shadow|enforce. All bundled CEL gates currently remain in per-rule shadow rollout, so global enforce mode does not suppress them until individual promotion. ATR is an optional --rule-packs atr input and is outside the current core + CEL release gate.


Generate and Customize a Policy

# Generate a policy YAML from a preset (any of the five)
skill-scanner generate-policy --preset low-noise -o my_policy.yaml

# Interactive TUI for editing every policy section
skill-scanner configure-policy -i my_policy.yaml -o my_policy.yaml

# Use the custom policy
skill-scanner scan ./my-skill --use-llm --policy my_policy.yaml

Merge Behavior

Custom policy files merge over defaults:

  • Missing keys inherit defaults from the base preset
  • Scalar fields override directly
  • Lists replace defaults entirely (they do not append)

Policy Sections

Policies cover file classification, analyzer behavior, adjudication, LLM budgets, finding normalization, and rule governance.

High-Impact Sections

SectionWhat It Controls
pipelineCommand-chain demotion, known installer handling, trusted domains, exfil hint words
rule_scopingWhich rules fire on which file types; docs vs code path gating
file_limitsMaximum file count, individual file size, nesting depth
analysis_thresholdsAnalyzability risk levels, unicode steganography sensitivity
analyzers.correlationBounded source/sink and staged-behavior correlation
cel.modeCEL decisions: off, shadow, or enforce
severity_overridesPer-rule severity remapping (promote or demote)
suppressionsSilence or re-rate a rule for named skills or paths only
disabled_rulesSwitch specific rule IDs off everywhere
adjudicatorEnable demote-only review and set the minimum false-positive confidence
llm_analysisPrompt/output budgets, caps on low-confidence and contextual-risk LLM findings, meta multiplier, and trusted reference domains

All Sections

SectionPurpose
analyzersEnable/disable core analyzers (static, bytecode, pipeline)
file_limitsSize, count, and depth constraints
file_classificationBinary tier mappings and hidden file allowlists
analysis_thresholdsAnalyzability scoring and unicode detection thresholds
rule_scopingRule-to-filetype mapping and doc-path exclusions
pipelineShell pipeline analysis tuning
command_safetyCommand risk tier classification
severity_overridesPer-rule severity adjustments
suppressionsScoped, expiring, audited exceptions for named skills or paths
disabled_rulesRules switched off everywhere
finding_outputDeduplication and co-occurrence annotation settings
metadataPolicy fingerprint and metadata attachment
llm_analysisLLM context/output budgets, LLM severity caps, meta multiplier, and trusted reference domains
adjudicatorPer-finding adjudication toggle and confidence threshold
docs_scanningDocumentation path scanning behavior
hidden_filesHidden file handling allowlists

Common Policy Tweaks

Demote a Noisy Rule (Visible, Not Gating)

severity_overrides:
  - rule_id: HIDDEN_DATA_FILE
    severity: LOW
    reason: "our skills ship dotfiles on purpose"

Promote a Rule to CRITICAL

severity_overrides:
  - rule_id: DATA_EXFIL_HTTP_POST
    severity: CRITICAL
    reason: "any outbound POST from a skill is a blocker for us"

Suppress a Reviewed Finding for One Skill or Path

suppressions:
  - rule_id: HOMOGLYPH_ATTACK
    skills: ["docs-translator"]
    reason: "Skill legitimately contains Cyrillic prose"
    expires: 2030-12-31

A suppressed finding no longer affects the verdict or exit code, but it is kept under suppressed_findings in JSON, and SARIF shows it as dismissed.

Switch a Rule Off Everywhere

disabled_rules:
  - BINARY_FILE_DETECTED

Disabled rules produce no findings at all. Prefer a severity override or a scoped suppression.

Cap the LLM Judge's Weakest Findings

llm_analysis:
  low_confidence_max_severity: LOW     # on in low-noise and quiet
  contextual_risk_max_severity: LOW    # on in quiet

Capped findings are still reported, at LOW. Results and Tuning shows what each cap costs in recall.

Restrict File Size Limits

file_limits:
  max_files: 50
  max_file_size_bytes: 1048576
  max_nesting_depth: 2

Adjust Analyzability Thresholds

analysis_thresholds:
  analyzability_low_risk: 90
  analyzability_medium_risk: 70

Trust Internal Reference Domains

llm_analysis:
  trusted_reference_domains:
    - git.example.com
    - packages.example.com

LLM transitive-trust and supply-chain findings that reference only these domains are demoted to LOW. Keep this list narrow and organization-controlled.

Configure Adjudication

adjudicator:
  enabled: true
  min_fp_confidence: 4

The adjudicator is demote-only, but an incorrect LLM verdict can still demote a real threat. It is disabled by default and records its decisions for audit.


Using Policies in the SDK

from skill_scanner import SkillScanner
from skill_scanner.core.scan_policy import ScanPolicy

# Use a built-in preset
policy = ScanPolicy.from_preset("low-noise")

# Or load a custom YAML file
policy = ScanPolicy.from_yaml("my_policy.yaml")

scanner = SkillScanner(policy=policy)
result = scanner.scan_skill("/path/to/skill")

Policy in CI/CD

Commit your custom policy to the repository and reference it in CI:

skill-scanner scan-all ./skills --use-llm --policy .github/scan-policy.yaml --fail-on-severity high

Or in GitHub Actions:

with:
  skill_path: .cursor/skills
  policy: .github/scan-policy.yaml
  use_llm: true
  llm_model: anthropic/claude-sonnet-5-5

Full Reference

For exhaustive knob-by-knob documentation of every policy field, see: