cisco-ai-skill-scanner 1.0.1__py3-none-any.whl → 1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {cisco_ai_skill_scanner-1.0.1.dist-info → cisco_ai_skill_scanner-1.0.2.dist-info}/METADATA +16 -1
  2. {cisco_ai_skill_scanner-1.0.1.dist-info → cisco_ai_skill_scanner-1.0.2.dist-info}/RECORD +37 -35
  3. skill_scanner/_version.py +2 -2
  4. skill_scanner/api/api_cli.py +2 -2
  5. skill_scanner/api/api_server.py +1 -1
  6. skill_scanner/cli/cli.py +60 -2
  7. skill_scanner/config/yara_modes.py +314 -0
  8. skill_scanner/core/analyzers/llm_analyzer.py +3 -3
  9. skill_scanner/core/analyzers/meta_analyzer.py +50 -18
  10. skill_scanner/core/analyzers/static.py +177 -27
  11. skill_scanner/core/models.py +1 -0
  12. skill_scanner/core/reporters/markdown_reporter.py +9 -3
  13. skill_scanner/core/static_analysis/context_extractor.py +87 -13
  14. skill_scanner/data/prompts/code_alignment_threat_analysis_prompt.md +103 -28
  15. skill_scanner/data/prompts/llm_response_schema.json +3 -3
  16. skill_scanner/data/prompts/skill_meta_analysis_prompt.md +10 -9
  17. skill_scanner/data/prompts/skill_threat_analysis_prompt.md +42 -6
  18. skill_scanner/data/rules/signatures.yaml +141 -35
  19. skill_scanner/data/yara_rules/autonomy_abuse_generic.yara +66 -0
  20. skill_scanner/data/yara_rules/{skill_discovery_abuse.yara → capability_inflation_generic.yara} +7 -4
  21. skill_scanner/data/yara_rules/code_execution_generic.yara +76 -0
  22. skill_scanner/data/yara_rules/{coercive_injection.yara → coercive_injection_generic.yara} +2 -2
  23. skill_scanner/data/yara_rules/command_injection_generic.yara +77 -0
  24. skill_scanner/data/yara_rules/{credential_harvesting.yara → credential_harvesting_generic.yara} +25 -4
  25. skill_scanner/data/yara_rules/{transitive_trust_abuse.yara → indirect_prompt_injection_generic.yara} +8 -5
  26. skill_scanner/data/yara_rules/{prompt_injection.yara → prompt_injection_generic.yara} +2 -2
  27. skill_scanner/data/yara_rules/{unicode_steganography.yara → prompt_injection_unicode_steganography.yara} +23 -17
  28. skill_scanner/data/yara_rules/script_injection_generic.yara +82 -0
  29. skill_scanner/data/yara_rules/{sql_injection.yara → sql_injection_generic.yara} +22 -8
  30. skill_scanner/data/yara_rules/system_manipulation_generic.yara +79 -0
  31. skill_scanner/data/yara_rules/tool_chaining_abuse_generic.yara +72 -0
  32. skill_scanner/threats/__init__.py +24 -2
  33. skill_scanner/threats/cisco_ai_taxonomy.py +274 -0
  34. skill_scanner/threats/threats.py +28 -99
  35. skill_scanner/data/yara_rules/autonomy_abuse.yara +0 -66
  36. skill_scanner/data/yara_rules/code_execution.yara +0 -61
  37. skill_scanner/data/yara_rules/command_injection.yara +0 -54
  38. skill_scanner/data/yara_rules/script_injection.yara +0 -83
  39. skill_scanner/data/yara_rules/system_manipulation.yara +0 -65
  40. skill_scanner/data/yara_rules/tool_chaining_abuse.yara +0 -60
  41. {cisco_ai_skill_scanner-1.0.1.dist-info → cisco_ai_skill_scanner-1.0.2.dist-info}/WHEEL +0 -0
  42. {cisco_ai_skill_scanner-1.0.1.dist-info → cisco_ai_skill_scanner-1.0.2.dist-info}/entry_points.txt +0 -0
  43. {cisco_ai_skill_scanner-1.0.1.dist-info → cisco_ai_skill_scanner-1.0.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cisco-ai-skill-scanner
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: Security scanner for Agent Skills packages - Detects prompt injection, data exfiltration, and malicious code
5
5
  Project-URL: Homepage, https://github.com/cisco-ai-defense/skill-scanner
6
6
  Project-URL: Documentation, https://github.com/cisco-ai-defense/skill-scanner#readme
@@ -167,6 +167,18 @@ skill-scanner scan-all /path/to/skills --recursive --use-behavioral
167
167
 
168
168
  # CI/CD: Fail build if threats found
169
169
  skill-scanner scan-all ./skills --fail-on-findings --format sarif --output results.sarif
170
+
171
+ # Use custom YARA rules
172
+ skill-scanner scan /path/to/skill --custom-rules /path/to/my-rules/
173
+
174
+ # Disable specific noisy rules
175
+ skill-scanner scan /path/to/skill --disable-rule YARA_script_injection --disable-rule MANIFEST_MISSING_LICENSE
176
+
177
+ # Strict mode (more findings, higher FP rate)
178
+ skill-scanner scan /path/to/skill --yara-mode strict
179
+
180
+ # Permissive mode (fewer findings, may miss some threats)
181
+ skill-scanner scan /path/to/skill --yara-mode permissive
170
182
  ```
171
183
 
172
184
  ### Python SDK
@@ -215,6 +227,9 @@ print(f"Findings: {len(result.findings)}")
215
227
  | `--format` | Output: `summary`, `json`, `markdown`, `table`, `sarif` |
216
228
  | `--output PATH` | Save report to file |
217
229
  | `--fail-on-findings` | Exit with error if HIGH/CRITICAL found |
230
+ | `--yara-mode` | Detection mode: `strict`, `balanced` (default), `permissive` |
231
+ | `--custom-rules PATH` | Use custom YARA rules from directory |
232
+ | `--disable-rule RULE` | Disable specific rule (can repeat) |
218
233
 
219
234
  ---
220
235
 
@@ -1,33 +1,34 @@
1
1
  skill_scanner/__init__.py,sha256=QuGYhgc529C5Cjtk3Th5t7-Qkx9kxOv6E2GK6soGZQw,1383
2
- skill_scanner/_version.py,sha256=JvmBpae6cHui8lSCsCcZQAxzawN2NERHGsr-rIUeJMo,704
2
+ skill_scanner/_version.py,sha256=ZTgKq8LPNy3l9uR2ke-VtLhvvl5l71frQ9wO76n1L5k,704
3
3
  skill_scanner/api/__init__.py,sha256=vhuGqXgBx70izjHQOa-cWm3cbHlKhkpEiRjpusQ49vo,746
4
4
  skill_scanner/api/api.py,sha256=5fFYh1e1JE06pNtZw-7zMcQMc791ubNlck0VjWzskq8,1027
5
- skill_scanner/api/api_cli.py,sha256=wMJHSrQWWSg5idCLaWa-irPqhigtt_o1QVukMKvpfGY,2372
6
- skill_scanner/api/api_server.py,sha256=cjN2P4xHXitKAI9aLztn9bKcFyVxm-2rpsy1OaVxwQo,21110
5
+ skill_scanner/api/api_cli.py,sha256=NcBQyhW1YtFi97A7btNMyC3wtBxk07dRsZdOhFNKt-Q,2378
6
+ skill_scanner/api/api_server.py,sha256=liHVVSOaLoYOYBGyg3DWKJSVPMZF7L26uPvLKrtg9R4,21112
7
7
  skill_scanner/api/router.py,sha256=3u5qPWO48iF09oIm-3oxYkqqO4hT50jCaNQTr2TBfYc,17411
8
8
  skill_scanner/cli/__init__.py,sha256=UOFAWN8z8nMviFLHiFrtlcHn4eGbbRZc4B2q8yWlTno,755
9
- skill_scanner/cli/cli.py,sha256=rnV2C2X-lNqSxPM3rNJ6J9Gde1kap9IAiBnOtpmCbXY,35485
9
+ skill_scanner/cli/cli.py,sha256=AFFJbsZ7GnA4bYUbivgqbjTWlWiwWU4oMGy96WBybkE,37747
10
10
  skill_scanner/config/__init__.py,sha256=S0hMvyq3Vi0wWET74XmbPQmBTBkLXtqFca5PcTYosUM,837
11
11
  skill_scanner/config/config.py,sha256=SvK9lvTNjpygc80pamDaGDtOhh99qGBG3EJiFKfEVzc,4698
12
12
  skill_scanner/config/config_parser.py,sha256=kGPawiniy35fyUoJvnwRsJsgtIiAjSXHhE3joUcZtn8,3772
13
13
  skill_scanner/config/constants.py,sha256=re2KkOtvSnxSJgkamdIU0fjdQ-fUSHX1eQSEfKDXjTA,2512
14
+ skill_scanner/config/yara_modes.py,sha256=1jgdVdLWC_oSJPuk4BCeUZU9lm9X7NwiDjTXeSCeGpw,11425
14
15
  skill_scanner/core/__init__.py,sha256=fC3n7lJs_G8CFz2Vg1gfGFe6b0pBiCUs7MRW4kCM1CY,822
15
16
  skill_scanner/core/exceptions.py,sha256=F4k2RDXIxrrnNsAsHn7wR277i2dNOXdK-NK0r-m3nF0,2007
16
17
  skill_scanner/core/loader.py,sha256=cIU7e5MZHxryr-7UiGwI76eM0Zbm-LrmRGI0mP1_17A,13541
17
- skill_scanner/core/models.py,sha256=vWAhDpAm4y8Flqp18cH4R4Vh8eOKNHrAHmsx68jXyOk,10551
18
+ skill_scanner/core/models.py,sha256=Zkp_CUHfXpWLSY_ceXLqazdIIqMJqaicWzxIQW0HgSk,10591
18
19
  skill_scanner/core/scanner.py,sha256=zAtM3Hbs_NNbYV7iq-9W2BURO-H23uRJ-E14S2h_wek,14830
19
20
  skill_scanner/core/analyzers/__init__.py,sha256=tctB8Q30gA5V4pdR5yoSpxyIKJZkFTJwowUq6UwddQo,2132
20
21
  skill_scanner/core/analyzers/aidefense_analyzer.py,sha256=ws61J3KJsz1DiuucBPCdsWN8ACI_iurtDQzWtFqfCA8,36468
21
22
  skill_scanner/core/analyzers/base.py,sha256=4BN6dHLn2Q9hQMLAJTSJXsl6tZgfCqqBxZO9icuu70Q,1374
22
23
  skill_scanner/core/analyzers/behavioral_analyzer.py,sha256=dvdTdwUKHqnmEa1nsChcdlJ0V_WvcZrGyHX5uYe0clI,19076
23
24
  skill_scanner/core/analyzers/cross_skill_scanner.py,sha256=MTedSXhLagZeXEtvkPV8m_48GqoHMWkh9rR9FR9puLQ,18934
24
- skill_scanner/core/analyzers/llm_analyzer.py,sha256=6_b0DYTPSA0opLNnQzyuAoVfxgI8PFkEhJEeB-Ajd3w,17835
25
+ skill_scanner/core/analyzers/llm_analyzer.py,sha256=biH2g_hych5dAecQL7bKi3GsW9P_nPGerRiEeoOLr2I,17963
25
26
  skill_scanner/core/analyzers/llm_prompt_builder.py,sha256=28OCgMUE0T-A6GkF5sUY0qPFvaKC1jhB6jPjVPbePsw,10160
26
27
  skill_scanner/core/analyzers/llm_provider_config.py,sha256=pbVx7N9OCohjIWjENMq-kiy6_svTn4IYvQfPxlR0M_Y,8488
27
28
  skill_scanner/core/analyzers/llm_request_handler.py,sha256=nz_gjnDTr0dT2GbfQMqKR6-n63x38AcB5G4UnPHLY9s,11679
28
29
  skill_scanner/core/analyzers/llm_response_parser.py,sha256=wO5ovd4se-KqIPwdZX-r0_tozaJEDUx7Q7yajKntPwk,2682
29
- skill_scanner/core/analyzers/meta_analyzer.py,sha256=oIMmRfIsS-LUa7qyTpS8HTrGu0TqpUbrrV6gUa5dugU,33371
30
- skill_scanner/core/analyzers/static.py,sha256=JAUYefYH1Oa3qnFmk78Sw7OuzcCwC1d8BFX6Hoh0wtM,45208
30
+ skill_scanner/core/analyzers/meta_analyzer.py,sha256=9nFZFinooTuKaAO-CM_HTJxopw2GPxnn5ZXvJ2ZORCU,35017
31
+ skill_scanner/core/analyzers/static.py,sha256=5mDPHbiD5jHxjGenfX68owXY6DqEkqaKRADkLpTQn48,51979
31
32
  skill_scanner/core/analyzers/trigger_analyzer.py,sha256=bmJjaGdSqsAyvOIehHbMjLrDWysd7YV9J9TXgMvTEe0,12268
32
33
  skill_scanner/core/analyzers/virustotal_analyzer.py,sha256=V7nG-fR2GhfdZhh8JVNvM6gOqRyUGsuxHN1yNRvmw6M,15988
33
34
  skill_scanner/core/analyzers/behavioral/__init__.py,sha256=aTuJyqDbylHE2Ags_LaYLbbOkkJxkTDP--VBU-KMPgs,1069
@@ -39,14 +40,14 @@ skill_scanner/core/analyzers/behavioral/alignment/alignment_response_validator.p
39
40
  skill_scanner/core/analyzers/behavioral/alignment/threat_vulnerability_classifier.py,sha256=DCXnbs9Fa2ajFT0We4sOo6nxIk7O_Pc0z01fGMDHsRg,7227
40
41
  skill_scanner/core/reporters/__init__.py,sha256=XCqeM_kiS1uvcwymDreueQ2KOzMhG5_4vQgxzReJS4w,943
41
42
  skill_scanner/core/reporters/json_reporter.py,sha256=JLlPTbs8ncMJHAXZk7iBWCHdL5Qn2PqHOQldHeH2ZGE,1798
42
- skill_scanner/core/reporters/markdown_reporter.py,sha256=SPLztJIhOVi0knocvSCCByWdsXWp3rQ1E63VGHaxgm8,7840
43
+ skill_scanner/core/reporters/markdown_reporter.py,sha256=khOEHC2mshwu97EF3KW2f00l-VvHpq0_HkVzCsWAKm8,8064
43
44
  skill_scanner/core/reporters/sarif_reporter.py,sha256=8BUUerHX-gpE-5HYAipfCLH3GdlVuul43ZItHDAB7Bw,8289
44
45
  skill_scanner/core/reporters/table_reporter.py,sha256=sotaDM2VzaX4vCR-OrF3GyIX_yv7wWhzS_doyc1I1XE,7044
45
46
  skill_scanner/core/rules/__init__.py,sha256=zGlTBVjihqxgg0BKmhdGkyeCzSvRjVEASjBh-M0sn_8,680
46
47
  skill_scanner/core/rules/patterns.py,sha256=OuJ6mPlQVy9R8g1Pn9ozWIC8iWfDEuQamdDW5Uu8200,5833
47
48
  skill_scanner/core/rules/yara_scanner.py,sha256=U-qYrb92n3664cTt7ynRTMVGGsxhfrSU0OOYV-BnxKc,5326
48
49
  skill_scanner/core/static_analysis/__init__.py,sha256=meZnZQj7ChgHek6fIrfd-YInolXCqI37HTUTlQWEm7w,930
49
- skill_scanner/core/static_analysis/context_extractor.py,sha256=bUOmrkwzUxAVD1_64TZt4eHOhzH42db1W39VPibdmk8,29785
50
+ skill_scanner/core/static_analysis/context_extractor.py,sha256=v3UUugDuC4WHGnHc2gcHLa6awlVpQZIBhCmCxFsuBes,32264
50
51
  skill_scanner/core/static_analysis/cfg/__init__.py,sha256=jkvx12ZGddbRVu_0b04Bamr7JX084yD6BLxgOUEHT1w,816
51
52
  skill_scanner/core/static_analysis/cfg/builder.py,sha256=Tm1GZ56rfOoNx-3WLmn2MNov2KzPKN-QZgJbBG-9D2c,14932
52
53
  skill_scanner/core/static_analysis/dataflow/__init__.py,sha256=eVdTh0JOvQvtKG96gqs_1VvIU0_sRNkV6sXZz6X9o7I,833
@@ -64,37 +65,38 @@ skill_scanner/core/static_analysis/taint/tracker.py,sha256=1WExA8NAV62X5Az64grI4
64
65
  skill_scanner/core/static_analysis/types/__init__.py,sha256=XluM6BlZ8ECfdAD-231ONJn13UeDdAGmirPAVc0zePk,937
65
66
  skill_scanner/data/__init__.py,sha256=eeZz0MhPMEV-PAx8Eqpbb4ey6EHbXT5g8j-DC4427A4,969
66
67
  skill_scanner/data/prompts/boilerplate_protection_rule_prompt.md,sha256=DNXYx13Mcbn2q9hw4msTDDbq_VcYCiVkqBZVFSNfzOg,1471
67
- skill_scanner/data/prompts/code_alignment_threat_analysis_prompt.md,sha256=OzOOFVCbhSHFYCd4Xg3_q0tIlOe32YRFOje-lZTyYws,25406
68
- skill_scanner/data/prompts/llm_response_schema.json,sha256=nBPlsOtuqv0zwIns4YY7uZsaAM0uPZ7mkcqe8tNDHl8,2971
69
- skill_scanner/data/prompts/skill_meta_analysis_prompt.md,sha256=aufAuj71GtMq9jwZfQoXAaZj0x43BAeBhC-fahc3bk4,13926
70
- skill_scanner/data/prompts/skill_threat_analysis_prompt.md,sha256=sg38JO8PvmxlpPudqzmUhGdv66A6d_Bj4dPiGVc_g8U,11629
68
+ skill_scanner/data/prompts/code_alignment_threat_analysis_prompt.md,sha256=j5U3YVKMM5HOndCl3cc_4CA190zBj9Z9tP8rLqz-M7c,25686
69
+ skill_scanner/data/prompts/llm_response_schema.json,sha256=xIxrWgPMWqL130AuV0-QkQIHAfQTK-NeJVPrsSIzL2s,3076
70
+ skill_scanner/data/prompts/skill_meta_analysis_prompt.md,sha256=_3jbZVKOiJx47V2d6rQ4sc4MpKFC9oN_7-c7_LxPUs8,14179
71
+ skill_scanner/data/prompts/skill_threat_analysis_prompt.md,sha256=ycE_a43c7qhUT6HwbP8zoKwTTNx3Nx4FyPuxicJ6r5I,11813
71
72
  skill_scanner/data/prompts/unified_response_schema.md,sha256=-f1EDpKzxjMMFFxXlakS3rORyLtD1_2XiuNwnty1nQs,3571
72
- skill_scanner/data/rules/signatures.yaml,sha256=EfP_gQk2tTNLNTaJK1si_yfg6XpmxGDGSaQCqpTnxvs,16465
73
- skill_scanner/data/yara_rules/autonomy_abuse.yara,sha256=5rbbKXvdWrrIi29T_nBhOQB9erUO8vqK_6TjWok-V2U,2581
74
- skill_scanner/data/yara_rules/code_execution.yara,sha256=mdXAEqi_Upphzt-NhGascbdG5hu8-UDEiRMfq0lgvWc,1896
75
- skill_scanner/data/yara_rules/coercive_injection.yara,sha256=3QNzoiHDyhk1zUXHv7_COtCBSsr-bb--H4wKeNRCbBM,5359
76
- skill_scanner/data/yara_rules/command_injection.yara,sha256=gwZ531smAPzLU1iodtX1JuZOyM_2RwKtBj_SfKjt_20,2163
77
- skill_scanner/data/yara_rules/credential_harvesting.yara,sha256=7W0pSKpW2KAmek1qP_DpjMHKuswv5L36tWusjuEl6Pc,5643
78
- skill_scanner/data/yara_rules/prompt_injection.yara,sha256=q5tT7-L__x9RCjdAbFLcs9mSs8gZOmPPzjbdNKRwIHE,2715
79
- skill_scanner/data/yara_rules/script_injection.yara,sha256=pzVPd7b9WNAS5iw8ZMoUgojKSBlEeSTLHLBho8UiMmA,3100
80
- skill_scanner/data/yara_rules/skill_discovery_abuse.yara,sha256=l1a2YESrARelhByvKxKaOdohKntMqxYGVcusp-1ZZCk,2452
81
- skill_scanner/data/yara_rules/sql_injection.yara,sha256=pWq3ccqEvQtWz4fU8dQOkhCgVl6US9SZJDfuBU_YCY4,3691
82
- skill_scanner/data/yara_rules/system_manipulation.yara,sha256=XoO17sZrarzdC58yyHaIz8z36x5xyxzmQXBnkYdoYfM,2231
83
- skill_scanner/data/yara_rules/tool_chaining_abuse.yara,sha256=1SyF3_j3VJysDvn1uKkuP9G7F4EhMYXMrq7Xcn1UURI,2255
84
- skill_scanner/data/yara_rules/transitive_trust_abuse.yara,sha256=8YMYbM5qwn-pqn8EFHJwpKvWyk__n9vEI7bH_MLzF2k,2772
85
- skill_scanner/data/yara_rules/unicode_steganography.yara,sha256=5UxTvcy8CeWJLrPeldgJ9rY5gfODlC9bTNOkCauuOJA,2650
73
+ skill_scanner/data/rules/signatures.yaml,sha256=GY41ZCvc2HIInwSnIYKLyHTK36J2hdOFyT-wRUhB3GU,19451
74
+ skill_scanner/data/yara_rules/autonomy_abuse_generic.yara,sha256=epgJRIj_qOYSZSsOQi4Tnv99T8rqbltNbZhECczRQXw,3097
75
+ skill_scanner/data/yara_rules/capability_inflation_generic.yara,sha256=RkDaqDtkcLULxr1Vb0XQ-5Q1BMwErkYcKx-sH6u0f1I,2610
76
+ skill_scanner/data/yara_rules/code_execution_generic.yara,sha256=c5W7h5Vl4rLgAabL9As4IkmNSbf4aAbzIH4kiaSYce4,3057
77
+ skill_scanner/data/yara_rules/coercive_injection_generic.yara,sha256=LQcfpAuzY1zC9N_xT-qfi72fCJm7mY0C2l89eFdTMKE,5363
78
+ skill_scanner/data/yara_rules/command_injection_generic.yara,sha256=vl1a4yYXloJk4lMFHbCmj16l0Th9IRDHu4_zH168sFY,3318
79
+ skill_scanner/data/yara_rules/credential_harvesting_generic.yara,sha256=iwgBlMt85i3VOrDkBMfHvwtO6PhF1Igh6m3Uj3CBOEI,7192
80
+ skill_scanner/data/yara_rules/indirect_prompt_injection_generic.yara,sha256=AHGYsEu6pRbNkpsb_sGOKaYSzpIR809ixxjxxRjaWY0,2977
81
+ skill_scanner/data/yara_rules/prompt_injection_generic.yara,sha256=OJMKzA1D6QXEEoogMnIeGp6NT308N5OY78uWjJBoODI,2752
82
+ skill_scanner/data/yara_rules/prompt_injection_unicode_steganography.yara,sha256=yALtLuRpoCu9toc5Wk3Av_W4GiWDFmpVNYaF2k3IAyk,3048
83
+ skill_scanner/data/yara_rules/script_injection_generic.yara,sha256=C4k3okg0APx0s4qxwSJc0swhp9AfAsACggnl-LYIoJg,3513
84
+ skill_scanner/data/yara_rules/sql_injection_generic.yara,sha256=Eu3EhTgYFGaOTjujMjwsjvnPrBihnfvq_9URCwDYyME,4642
85
+ skill_scanner/data/yara_rules/system_manipulation_generic.yara,sha256=hY1XmpYoKD6Eywwa51lL1DUXjwV7h1WRXk4TWYWzbic,3136
86
+ skill_scanner/data/yara_rules/tool_chaining_abuse_generic.yara,sha256=-sLNCZePTzk49exbQAorTCqKu-1bWWRD7oI6i2mj7kk,2867
86
87
  skill_scanner/hooks/__init__.py,sha256=W7_Xr71Edm6eHKz9_vZgpERbr0Wx2cyTxPn4YJaGg6o,739
87
88
  skill_scanner/hooks/pre_commit.py,sha256=dtajQcyAlSaH15J1O9HHQ67xrGj2P6M2pHN6MZ0htwY,13207
88
- skill_scanner/threats/__init__.py,sha256=9qlA659fV2Ngl-nV3INIrbVDvXzevHy0F9YAmu_kPWE,875
89
- skill_scanner/threats/threats.py,sha256=egFsT1crNlWQH3szG8yYIURMXXGh7GJnH3wI8w05nfI,21449
89
+ skill_scanner/threats/__init__.py,sha256=TpqVYCcjQGGpcsTR_1iIvrTT55Sd1ed15sVfGVfZJwk,1320
90
+ skill_scanner/threats/cisco_ai_taxonomy.py,sha256=pXBPgwqfFgKN8Jax3aue66v306aETX6bOSgoRu-zUMg,12910
91
+ skill_scanner/threats/threats.py,sha256=7r0V0HJFWI7m-PMoZECnwK3ANKyTzTYM3bEUG2tgUH8,17981
90
92
  skill_scanner/utils/__init__.py,sha256=mmzKMNaDQ3EtmD2zr_68gMatm4OETbVNtEXuVESxzJs,906
91
93
  skill_scanner/utils/command_utils.py,sha256=74rojYVuVWpv-HVdW0qTIzq0ySPdpBuyNTdIQZDakUM,4291
92
94
  skill_scanner/utils/di_container.py,sha256=O3aaQVKcu4t1YUXl9iCZxjSBXnvgddlTgmEp0De_g04,4585
93
95
  skill_scanner/utils/file_utils.py,sha256=LT2xwrbqIWaYC-BYAL9zpF6a2xk6QNUVzItvGGJcBn8,2043
94
96
  skill_scanner/utils/logging_config.py,sha256=8LJwRCVM-oED_6KRDvtjaL8cvEoR88seX1pDyILeQV4,2939
95
97
  skill_scanner/utils/logging_utils.py,sha256=CLdOYmQdJejiLbcECTT2CbDU27PJ327AFMmeuVfCy94,1902
96
- cisco_ai_skill_scanner-1.0.1.dist-info/METADATA,sha256=Ph3EsZ9hjAj9CbQGa8Cew3SM1iF3RfHowlfVifp_37I,9166
97
- cisco_ai_skill_scanner-1.0.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
98
- cisco_ai_skill_scanner-1.0.1.dist-info/entry_points.txt,sha256=Qpg94wQPc6kWF_KQ-jf2tL_wCJ3aJfZ4V4vsYz50GIw,175
99
- cisco_ai_skill_scanner-1.0.1.dist-info/licenses/LICENSE,sha256=b4va5sK_CWxpeDnOO2MF0MKqsiwU-3YblMmWKnmuWZg,653
100
- cisco_ai_skill_scanner-1.0.1.dist-info/RECORD,,
98
+ cisco_ai_skill_scanner-1.0.2.dist-info/METADATA,sha256=EzizoVjYbxLZk_xxnyv052t5bNdvd7APCYXzbDd-Xh8,9827
99
+ cisco_ai_skill_scanner-1.0.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
100
+ cisco_ai_skill_scanner-1.0.2.dist-info/entry_points.txt,sha256=Qpg94wQPc6kWF_KQ-jf2tL_wCJ3aJfZ4V4vsYz50GIw,175
101
+ cisco_ai_skill_scanner-1.0.2.dist-info/licenses/LICENSE,sha256=b4va5sK_CWxpeDnOO2MF0MKqsiwU-3YblMmWKnmuWZg,653
102
+ cisco_ai_skill_scanner-1.0.2.dist-info/RECORD,,
skill_scanner/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.0.1'
32
- __version_tuple__ = version_tuple = (1, 0, 1)
31
+ __version__ = version = '1.0.2'
32
+ __version_tuple__ = version_tuple = (1, 0, 2)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -39,11 +39,11 @@ Examples:
39
39
  skill-scanner-api --reload
40
40
 
41
41
  # Custom host and port
42
- skill-scanner-api --host 0.0.0.0 --port 9000
42
+ skill-scanner-api --host localhost --port 9000
43
43
  """,
44
44
  )
45
45
 
46
- parser.add_argument("--host", default="0.0.0.0", help="Host to bind to (default: 0.0.0.0)")
46
+ parser.add_argument("--host", default="localhost", help="Host to bind to (default: localhost)")
47
47
 
48
48
  parser.add_argument("--port", type=int, default=8000, help="Port to bind to (default: 8000)")
49
49
 
@@ -616,7 +616,7 @@ async def list_analyzers():
616
616
 
617
617
 
618
618
  # Entry point for running the server
619
- def run_server(host: str = "0.0.0.0", port: int = 8000, reload: bool = False):
619
+ def run_server(host: str = "localhost", port: int = 8000, reload: bool = False):
620
620
  """
621
621
  Run the API server.
622
622
 
skill_scanner/cli/cli.py CHANGED
@@ -62,8 +62,19 @@ def scan_command(args):
62
62
  print(f"Error: Directory does not exist: {skill_dir}", file=sys.stderr)
63
63
  return 1
64
64
 
65
+ # Get YARA mode and custom rules from args
66
+ yara_mode = getattr(args, "yara_mode", "balanced")
67
+ custom_rules_path = getattr(args, "custom_rules", None)
68
+ disabled_rules = set(getattr(args, "disabled_rules", None) or [])
69
+
65
70
  # Create scanner with configured analyzers
66
- analyzers = [StaticAnalyzer()]
71
+ analyzers = [
72
+ StaticAnalyzer(
73
+ yara_mode=yara_mode,
74
+ custom_yara_rules_path=custom_rules_path,
75
+ disabled_rules=disabled_rules,
76
+ )
77
+ ]
67
78
 
68
79
  # Helper to print status messages - go to stderr when JSON output to avoid breaking parsing
69
80
  is_json_output = getattr(args, "format", "summary") == "json"
@@ -273,8 +284,19 @@ def scan_all_command(args):
273
284
  print(f"Error: Directory does not exist: {skills_dir}", file=sys.stderr)
274
285
  return 1
275
286
 
287
+ # Get YARA mode and custom rules from args
288
+ yara_mode = getattr(args, "yara_mode", "balanced")
289
+ custom_rules_path = getattr(args, "custom_rules", None)
290
+ disabled_rules = set(getattr(args, "disabled_rules", None) or [])
291
+
276
292
  # Create scanner with configured analyzers
277
- analyzers = [StaticAnalyzer()]
293
+ analyzers = [
294
+ StaticAnalyzer(
295
+ yara_mode=yara_mode,
296
+ custom_yara_rules_path=custom_rules_path,
297
+ disabled_rules=disabled_rules,
298
+ )
299
+ ]
278
300
 
279
301
  # Helper to print status messages - go to stderr when JSON output to avoid breaking parsing
280
302
  is_json_output = getattr(args, "format", "summary") == "json"
@@ -728,6 +750,24 @@ Examples:
728
750
  action="store_true",
729
751
  help="Enable meta-analysis for false positive filtering and finding prioritization (requires 2+ analyzers including LLM)",
730
752
  )
753
+ scan_parser.add_argument(
754
+ "--yara-mode",
755
+ choices=["strict", "balanced", "permissive"],
756
+ default="balanced",
757
+ help="YARA detection mode: strict (max security, more FPs), balanced (default), permissive (fewer FPs, may miss threats)",
758
+ )
759
+ scan_parser.add_argument(
760
+ "--custom-rules",
761
+ metavar="PATH",
762
+ help="Path to directory containing custom YARA rules (.yara files) to use instead of built-in rules",
763
+ )
764
+ scan_parser.add_argument(
765
+ "--disable-rule",
766
+ action="append",
767
+ metavar="RULE_NAME",
768
+ dest="disabled_rules",
769
+ help="Disable a specific rule by name (can be used multiple times). Example: --disable-rule YARA_script_injection",
770
+ )
731
771
 
732
772
  # Scan-all command
733
773
  scan_all_parser = subparsers.add_parser("scan-all", help="Scan multiple skill packages")
@@ -783,6 +823,24 @@ Examples:
783
823
  action="store_true",
784
824
  help="Enable meta-analysis for false positive filtering and finding prioritization (requires 2+ analyzers including LLM)",
785
825
  )
826
+ scan_all_parser.add_argument(
827
+ "--yara-mode",
828
+ choices=["strict", "balanced", "permissive"],
829
+ default="balanced",
830
+ help="YARA detection mode: strict (max security, more FPs), balanced (default), permissive (fewer FPs, may miss threats)",
831
+ )
832
+ scan_all_parser.add_argument(
833
+ "--custom-rules",
834
+ metavar="PATH",
835
+ help="Path to directory containing custom YARA rules (.yara files) to use instead of built-in rules",
836
+ )
837
+ scan_all_parser.add_argument(
838
+ "--disable-rule",
839
+ action="append",
840
+ metavar="RULE_NAME",
841
+ dest="disabled_rules",
842
+ help="Disable a specific rule by name (can be used multiple times). Example: --disable-rule YARA_script_injection",
843
+ )
786
844
 
787
845
  # List analyzers command
788
846
  subparsers.add_parser("list-analyzers", help="List available analyzers")
@@ -0,0 +1,314 @@
1
+ # Copyright 2026 Cisco Systems, Inc. and its affiliates
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #
15
+ # SPDX-License-Identifier: Apache-2.0
16
+
17
+ """
18
+ YARA Mode Configuration System
19
+
20
+ Provides configurable detection modes to balance false positives vs true positives:
21
+ - STRICT: Maximum security, higher false positives acceptable
22
+ - BALANCED: Default mode, good tradeoff between FP and TP
23
+ - PERMISSIVE: Minimize false positives, may miss some threats
24
+ - CUSTOM: User-defined thresholds
25
+
26
+ Each mode configures:
27
+ - Rule-specific thresholds
28
+ - Post-processing filters
29
+ - Enabled/disabled rule sets
30
+ """
31
+
32
+ from dataclasses import dataclass, field
33
+ from enum import Enum
34
+ from typing import Optional
35
+
36
+
37
+ class YaraMode(Enum):
38
+ """YARA detection mode presets."""
39
+
40
+ STRICT = "strict"
41
+ BALANCED = "balanced"
42
+ PERMISSIVE = "permissive"
43
+ CUSTOM = "custom"
44
+
45
+
46
+ @dataclass
47
+ class UnicodeStegConfig:
48
+ """Configuration for unicode steganography detection."""
49
+
50
+ # Zero-width character thresholds
51
+ zerowidth_threshold_with_decode: int = 50 # When dangerous code is present
52
+ zerowidth_threshold_alone: int = 200 # Without dangerous code context
53
+
54
+ # Enable/disable specific patterns
55
+ detect_rtl_override: bool = True
56
+ detect_ltl_override: bool = True
57
+ detect_line_separators: bool = True
58
+ detect_unicode_tags: bool = True
59
+ detect_variation_selectors: bool = True
60
+
61
+
62
+ @dataclass
63
+ class CredentialHarvestingConfig:
64
+ """Configuration for credential harvesting detection."""
65
+
66
+ # Placeholder filtering
67
+ filter_placeholder_patterns: bool = True
68
+
69
+ # Specific API key patterns
70
+ detect_ai_api_keys: bool = True
71
+ detect_aws_keys: bool = True
72
+ detect_ssh_keys: bool = True
73
+ detect_env_exfiltration: bool = True
74
+
75
+
76
+ @dataclass
77
+ class ToolChainingConfig:
78
+ """Configuration for tool chaining abuse detection."""
79
+
80
+ # Post-filter settings
81
+ filter_api_documentation: bool = True
82
+ filter_generic_http_verbs: bool = True
83
+ filter_email_field_mentions: bool = True
84
+
85
+ # Pattern detection
86
+ detect_read_send: bool = True
87
+ detect_collect_exfil: bool = True
88
+ detect_env_network: bool = True
89
+
90
+
91
+ @dataclass
92
+ class YaraModeConfig:
93
+ """Complete YARA mode configuration."""
94
+
95
+ mode: YaraMode = YaraMode.BALANCED
96
+ description: str = ""
97
+
98
+ # Rule-specific configs
99
+ unicode_steg: UnicodeStegConfig = field(default_factory=UnicodeStegConfig)
100
+ credential_harvesting: CredentialHarvestingConfig = field(default_factory=CredentialHarvestingConfig)
101
+ tool_chaining: ToolChainingConfig = field(default_factory=ToolChainingConfig)
102
+
103
+ # Global settings
104
+ enabled_rules: set[str] = field(default_factory=set) # Empty = all enabled
105
+ disabled_rules: set[str] = field(default_factory=set)
106
+
107
+ @classmethod
108
+ def strict(cls) -> "YaraModeConfig":
109
+ """
110
+ STRICT mode: Maximum security, accept higher FP rate.
111
+
112
+ Use when:
113
+ - Scanning untrusted/external skills
114
+ - Security audit requirements
115
+ - Compliance scanning
116
+ """
117
+ return cls(
118
+ mode=YaraMode.STRICT,
119
+ description="Maximum security - flags more potential threats",
120
+ unicode_steg=UnicodeStegConfig(
121
+ zerowidth_threshold_with_decode=20, # Lower threshold
122
+ zerowidth_threshold_alone=100,
123
+ ),
124
+ credential_harvesting=CredentialHarvestingConfig(
125
+ filter_placeholder_patterns=False, # Don't filter - flag for review
126
+ ),
127
+ tool_chaining=ToolChainingConfig(
128
+ filter_api_documentation=False,
129
+ filter_generic_http_verbs=False,
130
+ ),
131
+ )
132
+
133
+ @classmethod
134
+ def balanced(cls) -> "YaraModeConfig":
135
+ """
136
+ BALANCED mode: Default - good tradeoff between FP and TP.
137
+
138
+ Use when:
139
+ - Regular skill scanning
140
+ - CI/CD pipeline integration
141
+ - Development workflow
142
+ """
143
+ return cls(
144
+ mode=YaraMode.BALANCED,
145
+ description="Balanced detection - default mode",
146
+ unicode_steg=UnicodeStegConfig(
147
+ zerowidth_threshold_with_decode=50,
148
+ zerowidth_threshold_alone=200,
149
+ ),
150
+ credential_harvesting=CredentialHarvestingConfig(
151
+ filter_placeholder_patterns=True,
152
+ ),
153
+ tool_chaining=ToolChainingConfig(
154
+ filter_api_documentation=True,
155
+ filter_generic_http_verbs=True,
156
+ filter_email_field_mentions=True,
157
+ ),
158
+ )
159
+
160
+ @classmethod
161
+ def permissive(cls) -> "YaraModeConfig":
162
+ """
163
+ PERMISSIVE mode: Minimize false positives.
164
+
165
+ Use when:
166
+ - Scanning trusted/internal skills
167
+ - High FP rate is disrupting workflow
168
+ - Focus on critical threats only
169
+ """
170
+ return cls(
171
+ mode=YaraMode.PERMISSIVE,
172
+ description="Minimal false positives - may miss some threats",
173
+ unicode_steg=UnicodeStegConfig(
174
+ zerowidth_threshold_with_decode=100, # Higher threshold
175
+ zerowidth_threshold_alone=500,
176
+ detect_line_separators=False, # Common in some content
177
+ ),
178
+ credential_harvesting=CredentialHarvestingConfig(
179
+ filter_placeholder_patterns=True,
180
+ ),
181
+ tool_chaining=ToolChainingConfig(
182
+ filter_api_documentation=True,
183
+ filter_generic_http_verbs=True,
184
+ filter_email_field_mentions=True,
185
+ ),
186
+ # Disable noisier rules
187
+ disabled_rules={
188
+ "capability_inflation_generic",
189
+ "indirect_prompt_injection_generic",
190
+ },
191
+ )
192
+
193
+ @classmethod
194
+ def custom(
195
+ cls,
196
+ unicode_steg: UnicodeStegConfig | None = None,
197
+ credential_harvesting: CredentialHarvestingConfig | None = None,
198
+ tool_chaining: ToolChainingConfig | None = None,
199
+ enabled_rules: set[str] | None = None,
200
+ disabled_rules: set[str] | None = None,
201
+ ) -> "YaraModeConfig":
202
+ """
203
+ CUSTOM mode: User-defined configuration.
204
+
205
+ Args:
206
+ unicode_steg: Unicode steganography config
207
+ credential_harvesting: Credential harvesting config
208
+ tool_chaining: Tool chaining config
209
+ enabled_rules: Set of rule names to enable (empty = all)
210
+ disabled_rules: Set of rule names to disable
211
+ """
212
+ return cls(
213
+ mode=YaraMode.CUSTOM,
214
+ description="Custom user-defined configuration",
215
+ unicode_steg=unicode_steg or UnicodeStegConfig(),
216
+ credential_harvesting=credential_harvesting or CredentialHarvestingConfig(),
217
+ tool_chaining=tool_chaining or ToolChainingConfig(),
218
+ enabled_rules=enabled_rules or set(),
219
+ disabled_rules=disabled_rules or set(),
220
+ )
221
+
222
+ @classmethod
223
+ def from_mode_name(cls, mode_name: str) -> "YaraModeConfig":
224
+ """Create config from mode name string."""
225
+ mode_map = {
226
+ "strict": cls.strict,
227
+ "balanced": cls.balanced,
228
+ "permissive": cls.permissive,
229
+ }
230
+ if mode_name.lower() in mode_map:
231
+ return mode_map[mode_name.lower()]()
232
+ raise ValueError(f"Unknown mode: {mode_name}. Use: strict, balanced, permissive, or custom")
233
+
234
+ def is_rule_enabled(self, rule_name: str) -> bool:
235
+ """Check if a specific rule is enabled in this mode."""
236
+ # If enabled_rules is specified, only those are allowed
237
+ if self.enabled_rules and rule_name not in self.enabled_rules:
238
+ return False
239
+ # Check if explicitly disabled
240
+ if rule_name in self.disabled_rules:
241
+ return False
242
+ return True
243
+
244
+ def to_dict(self) -> dict:
245
+ """Convert config to dictionary for serialization."""
246
+ return {
247
+ "mode": self.mode.value,
248
+ "description": self.description,
249
+ "unicode_steg": {
250
+ "zerowidth_threshold_with_decode": self.unicode_steg.zerowidth_threshold_with_decode,
251
+ "zerowidth_threshold_alone": self.unicode_steg.zerowidth_threshold_alone,
252
+ "detect_rtl_override": self.unicode_steg.detect_rtl_override,
253
+ "detect_ltl_override": self.unicode_steg.detect_ltl_override,
254
+ "detect_line_separators": self.unicode_steg.detect_line_separators,
255
+ "detect_unicode_tags": self.unicode_steg.detect_unicode_tags,
256
+ "detect_variation_selectors": self.unicode_steg.detect_variation_selectors,
257
+ },
258
+ "credential_harvesting": {
259
+ "filter_placeholder_patterns": self.credential_harvesting.filter_placeholder_patterns,
260
+ "detect_ai_api_keys": self.credential_harvesting.detect_ai_api_keys,
261
+ "detect_aws_keys": self.credential_harvesting.detect_aws_keys,
262
+ "detect_ssh_keys": self.credential_harvesting.detect_ssh_keys,
263
+ "detect_env_exfiltration": self.credential_harvesting.detect_env_exfiltration,
264
+ },
265
+ "tool_chaining": {
266
+ "filter_api_documentation": self.tool_chaining.filter_api_documentation,
267
+ "filter_generic_http_verbs": self.tool_chaining.filter_generic_http_verbs,
268
+ "filter_email_field_mentions": self.tool_chaining.filter_email_field_mentions,
269
+ "detect_read_send": self.tool_chaining.detect_read_send,
270
+ "detect_collect_exfil": self.tool_chaining.detect_collect_exfil,
271
+ "detect_env_network": self.tool_chaining.detect_env_network,
272
+ },
273
+ "enabled_rules": list(self.enabled_rules),
274
+ "disabled_rules": list(self.disabled_rules),
275
+ }
276
+
277
+
278
+ # Default mode
279
+ DEFAULT_YARA_MODE = YaraModeConfig.balanced()
280
+
281
+
282
+ # Mode descriptions for CLI/API documentation
283
+ MODE_DESCRIPTIONS = {
284
+ "strict": """
285
+ STRICT Mode - Maximum Security
286
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
287
+ • Lower detection thresholds
288
+ • Minimal post-processing filters
289
+ • Flags more potential threats
290
+ • Higher false positive rate acceptable
291
+
292
+ Use for: Untrusted skills, security audits, compliance
293
+ """,
294
+ "balanced": """
295
+ BALANCED Mode - Default
296
+ ━━━━━━━━━━━━━━━━━━━━━━━
297
+ • Moderate detection thresholds
298
+ • Context-aware post-processing
299
+ • Good tradeoff between FP and TP
300
+ • Suitable for most use cases
301
+
302
+ Use for: Regular scanning, CI/CD, development
303
+ """,
304
+ "permissive": """
305
+ PERMISSIVE Mode - Minimal False Positives
306
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
307
+ • Higher detection thresholds
308
+ • Aggressive filtering
309
+ • Focus on critical threats only
310
+ • May miss some edge-case threats
311
+
312
+ Use for: Trusted skills, high FP disruption
313
+ """,
314
+ }
@@ -277,12 +277,12 @@ class LLMAnalyzer(BaseAnalyzer):
277
277
 
278
278
  When selecting AITech codes for findings, use these mappings:
279
279
  - AITech-1.1: Direct prompt injection in SKILL.md (jailbreak, instruction override)
280
- - AITech-1.2: Indirect prompt injection (transitive trust, following untrusted content)
281
- - AITech-2.1: Social engineering (deceptive descriptions/metadata)
280
+ - AITech-1.2: Indirect prompt injection - instruction manipulation (embedding malicious instructions in external sources)
281
+ - AITech-4.3: Protocol manipulation - capability inflation (skill discovery abuse, keyword baiting, over-broad claims)
282
282
  - AITech-8.2: Data exfiltration/exposure (unauthorized access, credential theft, hardcoded secrets)
283
283
  - AITech-9.1: Model/agentic manipulation (command injection, code injection, SQL injection, obfuscation)
284
284
  - AITech-12.1: Tool exploitation (tool poisoning, shadowing, unauthorized use)
285
- - AITech-13.3: Availability disruption (resource abuse, DoS, infinite loops)
285
+ - AITech-13.1: Disruption of Availability (resource abuse, DoS, infinite loops) - AISubtech-13.1.1: Compute Exhaustion
286
286
  - AITech-15.1: Harmful/misleading content (deceptive content, misinformation)
287
287
 
288
288
  The structured output schema will enforce these exact codes.""",