Makefile, or as a required CI check so a skill is caught on the pull request instead of at publish time.
The same-engine guarantee
The local scanner is not a lookalike. Thedecimalai CLI imports and runs the exact Tier-1 scanner the publish gate runs — the same regex/AST-free rule set, versioned together — so a clean local run means the gate’s static tier will agree. Two things follow from that:
- What runs locally is Tier-1 only. The static scan catches prompt-injection phrasing, remote-code-execution and reverse-shell patterns, destructive commands, committed secrets, data-exfiltration and agent-snooping, cloud-metadata/SSRF, hidden-unicode and homoglyph tricks, over-broad
allowed-tools, and the rest of the deterministic checks. Secrets it finds are redacted, never echoed. - The LLM tiers stay server-side. The AI security review (Tier-2 intent judge) and content-safety review (Tier-3) need a model and run only on the platform. Exercise them with Deep Review on a private draft, or by hitting the publish gate itself.
Scan locally
Point the scanner at any directory; it recurses forSKILL.md files. The same command ships in both the DecimalAI CLI and the open-source skillevaluation runner — identical code, so pick whichever is already installed.
Output formats
--format controls how findings are rendered — the detection is identical across all four:
Exit codes
--fail-on sets the band at or above which the command exits non-zero. Combined with the exit code, that’s all a CI gate needs:
--fail-on accepts blocked (default), caution (stricter — fail on either band), or never (always exit 0, report only). Distinguish 1 from 2 in scripts: 1 is a real finding you should act on; 2 is an operational error you should fix before trusting the result.
In CI (GitHub Actions)
Two things worth doing on every pull request that touches a skill: annotate the diff inline so a reviewer sees findings in context, and (optionally) upload SARIF so Blocked findings become tracked code-scanning alerts. This workflow does both, and needs no secrets — the scan is fully local to the runner.--format githubmakes the scanner print GitHub workflow commands, so a Blocked finding surfaces as a red::errorand a Caution as a yellow::warning, pinned to the offending line in the PR’s Files changed view — no log-scrolling.- The gating step and the SARIF step are separate on purpose. The annotation step (
--fail-on blocked) owns the pass/fail decision. The SARIF step runs with--fail-on neverandif: always()so it produces a file and uploads even when the gate fails — otherwise a Blocked finding would abort the job before it was ever recorded as an alert. security-events: writeis required forupload-sarif;contents: readcovers the checkout. If you only want inline annotations and no code-scanning tab, drop the last two steps and thesecurity-eventspermission.
This is the same binary you run locally, so a green CI check and a green laptop run mean the same thing. To also gate on the LLM tiers before a PR merges, run Deep Review on the draft (metered; the publish gate is always free) rather than expecting the local scan to cover them.
Defense in depth: run an ensemble
The SkillSafety static scanner is one detector with one rule set. Static scanners each catch a slightly different slice, so the strongest CI posture is an ensemble — run more than one and act on the union. Two independent open scanners pair well as additional steps:
Both are third-party projects, not maintained by DecimalAI — add them as extra workflow steps alongside
decimalai skills scan, each writing its own annotations or SARIF. More detectors mean more redundancy: a genuinely malicious skill has to slip past all of them, not just one.
Related
skillevaluation
The open runner that ships the same
scan command — and the A/B benchmark beside it.Community Registry
Where the publish gate lives — the server-side counterpart to the local scan.
Security
DecimalAI’s platform security posture and data handling.