You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored
feat: allow --lenient to scan skills without SKILL.md (#63)
* feat: allow --lenient to scan skills without SKILL.md and fix jq pipe false positive
When --lenient is set and SKILL.md is absent, the loader now falls back to
scanning .md files in the directory as instruction bodies. This enables
scanning non-Codex/Cursor skill formats (Claude Code commands, flat markdown
repos) without requiring a shim.
Also adds --skill-file flag for specifying a custom metadata filename, updates
scan-all discovery to find .md-containing directories in lenient mode, and
fixes the pipeline taint analyzer splitting pipes inside quoted strings (e.g.
jq '.events[] | {source}' was incorrectly flagged as a bash source invocation).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update documentation for --lenient fallback, --skill-file, and jq fix
Update README, quick-start, CLI usage, CLI reference, scanning pipeline,
Python SDK, and FEATURE.md to document:
- --lenient now falls back to .md files when SKILL.md is absent
- New --skill-file flag for custom metadata filenames
- Quote-aware pipe splitting in the pipeline analyzer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Copy file name to clipboardExpand all lines: README.md
+10-2Lines changed: 10 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,7 @@ A best-effort security scanner for AI Agent Skills that detects prompt injection
13
13
14
14
> **Important:** This scanner provides best-effort detection, not comprehensive or complete coverage. A scan that returns no findings does not guarantee that a skill is free of all threats. See [Scope and Limitations](#scope-and-limitations) below.
15
15
16
-
Supports [OpenAI Codex Skills](https://openai.github.io/codex/) and [Cursor Agent Skills](https://docs.cursor.com/context/rules) formats following the [Agent Skills specification](https://agentskills.io).
16
+
Supports [OpenAI Codex Skills](https://openai.github.io/codex/) and [Cursor Agent Skills](https://docs.cursor.com/context/rules) formats following the [Agent Skills specification](https://agentskills.io). With `--lenient`, also scans non-standard formats such as Claude Code `.claude/commands/*.md` and flat markdown skill repos.
skill-scanner scan-all ./skills --fail-on-severity high --format sarif --output results.sarif
159
166
@@ -252,7 +259,8 @@ if not result.is_safe:
252
259
|`--custom-rules PATH`| Use custom YARA rules from directory |
253
260
|`--taxonomy PATH`| Load custom taxonomy profile (JSON/YAML) for this run |
254
261
|`--threat-mapping PATH`| Load custom scanner threat mapping profile (JSON) for this run |
255
-
|`--lenient`| Tolerate malformed skills (coerce bad fields, fill defaults) instead of failing |
262
+
|`--lenient`| Tolerate malformed skills (coerce bad fields, fill defaults) instead of failing. When `SKILL.md` is absent, falls back to scanning `.md` files in the directory |
263
+
|`--skill-file FILENAME`| Custom metadata filename to use instead of `SKILL.md` (e.g. `README.md`) |
Copy file name to clipboardExpand all lines: docs/architecture/scanning-pipeline.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -58,7 +58,8 @@ flowchart TD
58
58
## Stage 1: Load and Pre-process
59
59
60
60
1.**Load skill package** via `SkillLoader`:
61
-
- Validate skill directory and `SKILL.md`
61
+
- Validate skill directory and locate metadata file (`SKILL.md` by default, or `--skill-file`)
62
+
- When `--lenient` is set and no `SKILL.md` exists, fall back to scanning `.md` files in the directory as instruction bodies (supports non-Codex/Cursor formats such as Claude Code commands)
Tolerate malformed skills (missing fields, non-string descriptions) instead of failing:
203
+
Tolerate malformed skills (missing fields, non-string descriptions) instead of failing. When `SKILL.md` is absent, lenient mode falls back to scanning `.md` files in the directory as instruction bodies — enabling support for non-Codex/Cursor formats such as Claude Code `.claude/commands/*.md`:
Copy file name to clipboardExpand all lines: docs/reference/cli-command-reference.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -35,7 +35,8 @@ Flags shared by `scan` and `scan-all`:
35
35
|`--enable-meta`| off | Enable the meta (cross-correlation) analyzer |
36
36
|`--fail-on-findings`| off | Exit non-zero if critical or high findings are reported; equivalent to `--fail-on-severity high` (CI gate) |
37
37
|`--fail-on-severity LEVEL`| off | Exit non-zero if findings at or above LEVEL exist (critical, high, medium, low, info) |
38
-
|`--lenient`| off | Tolerate malformed skills: coerce bad fields, fill defaults, and continue instead of failing |
38
+
|`--lenient`| off | Tolerate malformed skills: coerce bad fields, fill defaults, and continue instead of failing. When `SKILL.md` is absent, falls back to scanning `.md` files in the directory |
39
+
|`--skill-file FILENAME`|`SKILL.md`| Custom metadata filename to use instead of `SKILL.md`|
39
40
|`--detailed`| off | Include full evidence in output |
40
41
|`--compact`| off | Minimize output (JSON: no pretty-print) |
Scan a single skill package directory. Pass `lenient=True` to coerce malformed manifests instead of raising an error.
37
+
Scan a single skill package directory. Pass `lenient=True` to coerce malformed manifests instead of raising an error. When `lenient=True` and no `SKILL.md` exists, the loader falls back to scanning `.md` files in the directory. Pass `skill_file` to use a custom metadata filename (e.g. `"README.md"`).
38
38
39
39
```python
40
40
result = scanner.scan_skill("/path/to/skill")
41
+
42
+
# Scan a directory without SKILL.md (e.g. Claude Code commands)
43
+
result = scanner.scan_skill(".claude/commands/deploy", lenient=True)
44
+
45
+
# Use a custom metadata file
46
+
result = scanner.scan_skill("/path/to/skill", skill_file="README.md")
Scan all skill packages in a directory. When `lenient=True`, directories containing `.md` files (but no `SKILL.md`) are also discovered as candidate skills.
0 commit comments