@elizaos/skills 2.0.0-alpha.3

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 (371) hide show
  1. package/README.md +126 -0
  2. package/package.json +53 -0
  3. package/skills/1password/SKILL.md +70 -0
  4. package/skills/1password/references/cli-examples.md +29 -0
  5. package/skills/1password/references/get-started.md +17 -0
  6. package/skills/apple-notes/SKILL.md +77 -0
  7. package/skills/apple-reminders/SKILL.md +96 -0
  8. package/skills/bear-notes/SKILL.md +107 -0
  9. package/skills/bird/SKILL.md +224 -0
  10. package/skills/blogwatcher/SKILL.md +69 -0
  11. package/skills/blucli/SKILL.md +47 -0
  12. package/skills/bluebubbles/SKILL.md +131 -0
  13. package/skills/camsnap/SKILL.md +45 -0
  14. package/skills/canvas/SKILL.md +203 -0
  15. package/skills/clawhub/SKILL.md +77 -0
  16. package/skills/coding-agent/SKILL.md +284 -0
  17. package/skills/discord/SKILL.md +578 -0
  18. package/skills/eightctl/SKILL.md +50 -0
  19. package/skills/food-order/SKILL.md +48 -0
  20. package/skills/gemini/SKILL.md +43 -0
  21. package/skills/gifgrep/SKILL.md +79 -0
  22. package/skills/github/SKILL.md +77 -0
  23. package/skills/gog/SKILL.md +116 -0
  24. package/skills/goplaces/SKILL.md +52 -0
  25. package/skills/healthcheck/SKILL.md +245 -0
  26. package/skills/himalaya/SKILL.md +257 -0
  27. package/skills/himalaya/references/configuration.md +184 -0
  28. package/skills/himalaya/references/message-composition.md +199 -0
  29. package/skills/imsg/SKILL.md +74 -0
  30. package/skills/local-places/SERVER_README.md +101 -0
  31. package/skills/local-places/SKILL.md +102 -0
  32. package/skills/local-places/pyproject.toml +21 -0
  33. package/skills/local-places/src/local_places/__init__.py +2 -0
  34. package/skills/local-places/src/local_places/google_places.py +314 -0
  35. package/skills/local-places/src/local_places/main.py +65 -0
  36. package/skills/local-places/src/local_places/schemas.py +107 -0
  37. package/skills/mcporter/SKILL.md +61 -0
  38. package/skills/model-usage/SKILL.md +69 -0
  39. package/skills/model-usage/references/codexbar-cli.md +33 -0
  40. package/skills/model-usage/scripts/model_usage.py +310 -0
  41. package/skills/nano-banana-pro/SKILL.md +58 -0
  42. package/skills/nano-banana-pro/scripts/generate_image.py +184 -0
  43. package/skills/nano-pdf/SKILL.md +38 -0
  44. package/skills/notion/SKILL.md +172 -0
  45. package/skills/obsidian/SKILL.md +81 -0
  46. package/skills/openai-image-gen/SKILL.md +89 -0
  47. package/skills/openai-image-gen/scripts/gen.py +240 -0
  48. package/skills/openai-whisper/SKILL.md +38 -0
  49. package/skills/openai-whisper-api/SKILL.md +52 -0
  50. package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
  51. package/skills/openhue/SKILL.md +51 -0
  52. package/skills/oracle/SKILL.md +125 -0
  53. package/skills/ordercli/SKILL.md +78 -0
  54. package/skills/peekaboo/SKILL.md +190 -0
  55. package/skills/sag/SKILL.md +87 -0
  56. package/skills/security-ask-questions-if-underspecified/.claude-plugin/plugin.json +10 -0
  57. package/skills/security-ask-questions-if-underspecified/README.md +24 -0
  58. package/skills/security-ask-questions-if-underspecified/skills/ask-questions-if-underspecified/SKILL.md +85 -0
  59. package/skills/security-audit-context-building/.claude-plugin/plugin.json +10 -0
  60. package/skills/security-audit-context-building/README.md +58 -0
  61. package/skills/security-audit-context-building/commands/audit-context.md +21 -0
  62. package/skills/security-audit-context-building/skills/audit-context-building/SKILL.md +297 -0
  63. package/skills/security-audit-context-building/skills/audit-context-building/resources/COMPLETENESS_CHECKLIST.md +47 -0
  64. package/skills/security-audit-context-building/skills/audit-context-building/resources/FUNCTION_MICRO_ANALYSIS_EXAMPLE.md +355 -0
  65. package/skills/security-audit-context-building/skills/audit-context-building/resources/OUTPUT_REQUIREMENTS.md +71 -0
  66. package/skills/security-building-secure-contracts/.claude-plugin/plugin.json +10 -0
  67. package/skills/security-building-secure-contracts/README.md +241 -0
  68. package/skills/security-building-secure-contracts/skills/algorand-vulnerability-scanner/SKILL.md +284 -0
  69. package/skills/security-building-secure-contracts/skills/algorand-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +405 -0
  70. package/skills/security-building-secure-contracts/skills/audit-prep-assistant/SKILL.md +409 -0
  71. package/skills/security-building-secure-contracts/skills/cairo-vulnerability-scanner/SKILL.md +329 -0
  72. package/skills/security-building-secure-contracts/skills/cairo-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +722 -0
  73. package/skills/security-building-secure-contracts/skills/code-maturity-assessor/SKILL.md +218 -0
  74. package/skills/security-building-secure-contracts/skills/code-maturity-assessor/resources/ASSESSMENT_CRITERIA.md +355 -0
  75. package/skills/security-building-secure-contracts/skills/code-maturity-assessor/resources/EXAMPLE_REPORT.md +248 -0
  76. package/skills/security-building-secure-contracts/skills/code-maturity-assessor/resources/REPORT_FORMAT.md +33 -0
  77. package/skills/security-building-secure-contracts/skills/cosmos-vulnerability-scanner/SKILL.md +334 -0
  78. package/skills/security-building-secure-contracts/skills/cosmos-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +740 -0
  79. package/skills/security-building-secure-contracts/skills/guidelines-advisor/SKILL.md +252 -0
  80. package/skills/security-building-secure-contracts/skills/guidelines-advisor/resources/ASSESSMENT_AREAS.md +329 -0
  81. package/skills/security-building-secure-contracts/skills/guidelines-advisor/resources/DELIVERABLES.md +118 -0
  82. package/skills/security-building-secure-contracts/skills/guidelines-advisor/resources/EXAMPLE_REPORT.md +298 -0
  83. package/skills/security-building-secure-contracts/skills/secure-workflow-guide/SKILL.md +161 -0
  84. package/skills/security-building-secure-contracts/skills/secure-workflow-guide/resources/EXAMPLE_REPORT.md +279 -0
  85. package/skills/security-building-secure-contracts/skills/secure-workflow-guide/resources/WORKFLOW_STEPS.md +132 -0
  86. package/skills/security-building-secure-contracts/skills/solana-vulnerability-scanner/SKILL.md +389 -0
  87. package/skills/security-building-secure-contracts/skills/solana-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +669 -0
  88. package/skills/security-building-secure-contracts/skills/substrate-vulnerability-scanner/SKILL.md +298 -0
  89. package/skills/security-building-secure-contracts/skills/substrate-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +791 -0
  90. package/skills/security-building-secure-contracts/skills/token-integration-analyzer/SKILL.md +362 -0
  91. package/skills/security-building-secure-contracts/skills/token-integration-analyzer/resources/ASSESSMENT_CATEGORIES.md +571 -0
  92. package/skills/security-building-secure-contracts/skills/token-integration-analyzer/resources/REPORT_TEMPLATES.md +141 -0
  93. package/skills/security-building-secure-contracts/skills/ton-vulnerability-scanner/SKILL.md +388 -0
  94. package/skills/security-building-secure-contracts/skills/ton-vulnerability-scanner/resources/VULNERABILITY_PATTERNS.md +595 -0
  95. package/skills/security-burpsuite-project-parser/.claude-plugin/plugin.json +10 -0
  96. package/skills/security-burpsuite-project-parser/README.md +103 -0
  97. package/skills/security-burpsuite-project-parser/commands/burp-search.md +18 -0
  98. package/skills/security-burpsuite-project-parser/skills/SKILL.md +358 -0
  99. package/skills/security-burpsuite-project-parser/skills/scripts/burp-search.sh +99 -0
  100. package/skills/security-claude-in-chrome-troubleshooting/.claude-plugin/plugin.json +8 -0
  101. package/skills/security-claude-in-chrome-troubleshooting/README.md +31 -0
  102. package/skills/security-claude-in-chrome-troubleshooting/skills/claude-in-chrome-troubleshooting/SKILL.md +251 -0
  103. package/skills/security-constant-time-analysis/.claude-plugin/plugin.json +9 -0
  104. package/skills/security-constant-time-analysis/README.md +381 -0
  105. package/skills/security-constant-time-analysis/commands/ct-check.md +20 -0
  106. package/skills/security-constant-time-analysis/ct_analyzer/__init__.py +49 -0
  107. package/skills/security-constant-time-analysis/ct_analyzer/analyzer.py +1284 -0
  108. package/skills/security-constant-time-analysis/ct_analyzer/script_analyzers.py +3081 -0
  109. package/skills/security-constant-time-analysis/ct_analyzer/tests/__init__.py +1 -0
  110. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_analyzer.py +1397 -0
  111. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/bn_excerpt.js +205 -0
  112. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/decompose_constant_time.c +181 -0
  113. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/decompose_vulnerable.c +74 -0
  114. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/decompose_vulnerable.go +78 -0
  115. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/decompose_vulnerable.rs +92 -0
  116. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/vulnerable.cs +174 -0
  117. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/vulnerable.java +161 -0
  118. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/vulnerable.kt +181 -0
  119. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/vulnerable.php +140 -0
  120. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/vulnerable.py +252 -0
  121. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/vulnerable.rb +188 -0
  122. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/vulnerable.swift +199 -0
  123. package/skills/security-constant-time-analysis/ct_analyzer/tests/test_samples/vulnerable.ts +154 -0
  124. package/skills/security-constant-time-analysis/pyproject.toml +52 -0
  125. package/skills/security-constant-time-analysis/skills/constant-time-analysis/README.md +90 -0
  126. package/skills/security-constant-time-analysis/skills/constant-time-analysis/SKILL.md +219 -0
  127. package/skills/security-constant-time-analysis/skills/constant-time-analysis/references/compiled.md +129 -0
  128. package/skills/security-constant-time-analysis/skills/constant-time-analysis/references/javascript.md +136 -0
  129. package/skills/security-constant-time-analysis/skills/constant-time-analysis/references/kotlin.md +252 -0
  130. package/skills/security-constant-time-analysis/skills/constant-time-analysis/references/php.md +172 -0
  131. package/skills/security-constant-time-analysis/skills/constant-time-analysis/references/python.md +179 -0
  132. package/skills/security-constant-time-analysis/skills/constant-time-analysis/references/ruby.md +198 -0
  133. package/skills/security-constant-time-analysis/skills/constant-time-analysis/references/swift.md +288 -0
  134. package/skills/security-constant-time-analysis/skills/constant-time-analysis/references/vm-compiled.md +354 -0
  135. package/skills/security-constant-time-analysis/uv.lock +8 -0
  136. package/skills/security-culture-index/.claude-plugin/plugin.json +8 -0
  137. package/skills/security-culture-index/README.md +79 -0
  138. package/skills/security-culture-index/skills/interpreting-culture-index/SKILL.md +293 -0
  139. package/skills/security-culture-index/skills/interpreting-culture-index/references/anti-patterns.md +255 -0
  140. package/skills/security-culture-index/skills/interpreting-culture-index/references/conversation-starters.md +408 -0
  141. package/skills/security-culture-index/skills/interpreting-culture-index/references/interview-trait-signals.md +253 -0
  142. package/skills/security-culture-index/skills/interpreting-culture-index/references/motivators.md +158 -0
  143. package/skills/security-culture-index/skills/interpreting-culture-index/references/patterns-archetypes.md +147 -0
  144. package/skills/security-culture-index/skills/interpreting-culture-index/references/primary-traits.md +307 -0
  145. package/skills/security-culture-index/skills/interpreting-culture-index/references/secondary-traits.md +228 -0
  146. package/skills/security-culture-index/skills/interpreting-culture-index/references/team-composition.md +148 -0
  147. package/skills/security-culture-index/skills/interpreting-culture-index/scripts/check_deps.py +108 -0
  148. package/skills/security-culture-index/skills/interpreting-culture-index/scripts/culture_index/__init__.py +20 -0
  149. package/skills/security-culture-index/skills/interpreting-culture-index/scripts/culture_index/constants.py +122 -0
  150. package/skills/security-culture-index/skills/interpreting-culture-index/scripts/culture_index/extract.py +187 -0
  151. package/skills/security-culture-index/skills/interpreting-culture-index/scripts/culture_index/models.py +16 -0
  152. package/skills/security-culture-index/skills/interpreting-culture-index/scripts/culture_index/opencv_extractor.py +520 -0
  153. package/skills/security-culture-index/skills/interpreting-culture-index/scripts/extract_pdf.py +237 -0
  154. package/skills/security-culture-index/skills/interpreting-culture-index/scripts/pyproject.toml +18 -0
  155. package/skills/security-culture-index/skills/interpreting-culture-index/templates/burnout-report.md +113 -0
  156. package/skills/security-culture-index/skills/interpreting-culture-index/templates/comparison-report.md +103 -0
  157. package/skills/security-culture-index/skills/interpreting-culture-index/templates/hiring-profile.md +127 -0
  158. package/skills/security-culture-index/skills/interpreting-culture-index/templates/individual-report.md +85 -0
  159. package/skills/security-culture-index/skills/interpreting-culture-index/templates/predicted-profile.md +165 -0
  160. package/skills/security-culture-index/skills/interpreting-culture-index/templates/team-report.md +109 -0
  161. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/analyze-team.md +188 -0
  162. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/coach-manager.md +267 -0
  163. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/compare-profiles.md +188 -0
  164. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/define-hiring-profile.md +220 -0
  165. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/detect-burnout.md +206 -0
  166. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/extract-from-pdf.md +121 -0
  167. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/interpret-individual.md +183 -0
  168. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/interview-debrief.md +234 -0
  169. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/mediate-conflict.md +306 -0
  170. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/plan-onboarding.md +322 -0
  171. package/skills/security-culture-index/skills/interpreting-culture-index/workflows/predict-from-interview.md +250 -0
  172. package/skills/security-differential-review/.claude-plugin/plugin.json +10 -0
  173. package/skills/security-differential-review/README.md +109 -0
  174. package/skills/security-differential-review/commands/diff-review.md +21 -0
  175. package/skills/security-differential-review/skills/differential-review/SKILL.md +220 -0
  176. package/skills/security-differential-review/skills/differential-review/adversarial.md +203 -0
  177. package/skills/security-differential-review/skills/differential-review/methodology.md +234 -0
  178. package/skills/security-differential-review/skills/differential-review/patterns.md +300 -0
  179. package/skills/security-differential-review/skills/differential-review/reporting.md +369 -0
  180. package/skills/security-dwarf-expert/.claude-plugin/plugin.json +10 -0
  181. package/skills/security-dwarf-expert/README.md +38 -0
  182. package/skills/security-dwarf-expert/skills/dwarf-expert/SKILL.md +93 -0
  183. package/skills/security-dwarf-expert/skills/dwarf-expert/reference/coding.md +31 -0
  184. package/skills/security-dwarf-expert/skills/dwarf-expert/reference/dwarfdump.md +50 -0
  185. package/skills/security-dwarf-expert/skills/dwarf-expert/reference/readelf.md +8 -0
  186. package/skills/security-entry-point-analyzer/.claude-plugin/plugin.json +10 -0
  187. package/skills/security-entry-point-analyzer/README.md +74 -0
  188. package/skills/security-entry-point-analyzer/commands/entry-points.md +18 -0
  189. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/SKILL.md +251 -0
  190. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/cosmwasm.md +182 -0
  191. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/move-aptos.md +107 -0
  192. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/move-sui.md +87 -0
  193. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/solana.md +155 -0
  194. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/solidity.md +135 -0
  195. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/ton.md +185 -0
  196. package/skills/security-entry-point-analyzer/skills/entry-point-analyzer/references/vyper.md +141 -0
  197. package/skills/security-firebase-apk-scanner/.claude-plugin/plugin.json +10 -0
  198. package/skills/security-firebase-apk-scanner/README.md +85 -0
  199. package/skills/security-firebase-apk-scanner/commands/scan-apk.md +18 -0
  200. package/skills/security-firebase-apk-scanner/scanner.sh +1408 -0
  201. package/skills/security-firebase-apk-scanner/skills/firebase-apk-scanner/SKILL.md +197 -0
  202. package/skills/security-firebase-apk-scanner/skills/firebase-apk-scanner/references/vulnerabilities.md +803 -0
  203. package/skills/security-fix-review/.claude-plugin/plugin.json +13 -0
  204. package/skills/security-fix-review/README.md +118 -0
  205. package/skills/security-fix-review/commands/fix-review.md +24 -0
  206. package/skills/security-fix-review/skills/fix-review/SKILL.md +264 -0
  207. package/skills/security-fix-review/skills/fix-review/references/bug-detection.md +408 -0
  208. package/skills/security-fix-review/skills/fix-review/references/finding-matching.md +298 -0
  209. package/skills/security-fix-review/skills/fix-review/references/report-parsing.md +398 -0
  210. package/skills/security-insecure-defaults/.claude-plugin/plugin.json +10 -0
  211. package/skills/security-insecure-defaults/README.md +45 -0
  212. package/skills/security-insecure-defaults/skills/insecure-defaults/SKILL.md +117 -0
  213. package/skills/security-insecure-defaults/skills/insecure-defaults/references/examples.md +409 -0
  214. package/skills/security-modern-python/.claude-plugin/plugin.json +10 -0
  215. package/skills/security-modern-python/README.md +58 -0
  216. package/skills/security-modern-python/hooks/hooks.json +16 -0
  217. package/skills/security-modern-python/hooks/intercept-legacy-python.bats +388 -0
  218. package/skills/security-modern-python/hooks/intercept-legacy-python.sh +109 -0
  219. package/skills/security-modern-python/hooks/test_helper.bash +75 -0
  220. package/skills/security-modern-python/skills/modern-python/SKILL.md +333 -0
  221. package/skills/security-modern-python/skills/modern-python/references/dependabot.md +43 -0
  222. package/skills/security-modern-python/skills/modern-python/references/migration-checklist.md +141 -0
  223. package/skills/security-modern-python/skills/modern-python/references/pep723-scripts.md +259 -0
  224. package/skills/security-modern-python/skills/modern-python/references/prek.md +211 -0
  225. package/skills/security-modern-python/skills/modern-python/references/pyproject.md +254 -0
  226. package/skills/security-modern-python/skills/modern-python/references/ruff-config.md +240 -0
  227. package/skills/security-modern-python/skills/modern-python/references/security-setup.md +255 -0
  228. package/skills/security-modern-python/skills/modern-python/references/testing.md +284 -0
  229. package/skills/security-modern-python/skills/modern-python/references/uv-commands.md +200 -0
  230. package/skills/security-modern-python/skills/modern-python/templates/dependabot.yml +36 -0
  231. package/skills/security-modern-python/skills/modern-python/templates/pre-commit-config.yaml +66 -0
  232. package/skills/security-property-based-testing/.claude-plugin/plugin.json +9 -0
  233. package/skills/security-property-based-testing/README.md +47 -0
  234. package/skills/security-property-based-testing/skills/property-based-testing/README.md +88 -0
  235. package/skills/security-property-based-testing/skills/property-based-testing/SKILL.md +109 -0
  236. package/skills/security-property-based-testing/skills/property-based-testing/references/design.md +191 -0
  237. package/skills/security-property-based-testing/skills/property-based-testing/references/generating.md +200 -0
  238. package/skills/security-property-based-testing/skills/property-based-testing/references/libraries.md +130 -0
  239. package/skills/security-property-based-testing/skills/property-based-testing/references/refactoring.md +181 -0
  240. package/skills/security-property-based-testing/skills/property-based-testing/references/reviewing.md +209 -0
  241. package/skills/security-property-based-testing/skills/property-based-testing/references/strategies.md +124 -0
  242. package/skills/semgrep-rule-creator/.claude-plugin/plugin.json +8 -0
  243. package/skills/semgrep-rule-creator/README.md +43 -0
  244. package/skills/semgrep-rule-creator/commands/semgrep-rule.md +26 -0
  245. package/skills/semgrep-rule-creator/skills/semgrep-rule-creator/SKILL.md +168 -0
  246. package/skills/semgrep-rule-creator/skills/semgrep-rule-creator/references/quick-reference.md +203 -0
  247. package/skills/semgrep-rule-creator/skills/semgrep-rule-creator/references/workflow.md +240 -0
  248. package/skills/semgrep-rule-variant-creator/.claude-plugin/plugin.json +9 -0
  249. package/skills/semgrep-rule-variant-creator/README.md +86 -0
  250. package/skills/semgrep-rule-variant-creator/skills/semgrep-rule-variant-creator/SKILL.md +205 -0
  251. package/skills/semgrep-rule-variant-creator/skills/semgrep-rule-variant-creator/references/applicability-analysis.md +250 -0
  252. package/skills/semgrep-rule-variant-creator/skills/semgrep-rule-variant-creator/references/language-syntax-guide.md +324 -0
  253. package/skills/semgrep-rule-variant-creator/skills/semgrep-rule-variant-creator/references/workflow.md +518 -0
  254. package/skills/session-logs/SKILL.md +115 -0
  255. package/skills/sharp-edges/.claude-plugin/plugin.json +10 -0
  256. package/skills/sharp-edges/README.md +48 -0
  257. package/skills/sharp-edges/skills/sharp-edges/SKILL.md +292 -0
  258. package/skills/sharp-edges/skills/sharp-edges/references/auth-patterns.md +252 -0
  259. package/skills/sharp-edges/skills/sharp-edges/references/case-studies.md +274 -0
  260. package/skills/sharp-edges/skills/sharp-edges/references/config-patterns.md +333 -0
  261. package/skills/sharp-edges/skills/sharp-edges/references/crypto-apis.md +190 -0
  262. package/skills/sharp-edges/skills/sharp-edges/references/lang-c.md +205 -0
  263. package/skills/sharp-edges/skills/sharp-edges/references/lang-csharp.md +285 -0
  264. package/skills/sharp-edges/skills/sharp-edges/references/lang-go.md +270 -0
  265. package/skills/sharp-edges/skills/sharp-edges/references/lang-java.md +263 -0
  266. package/skills/sharp-edges/skills/sharp-edges/references/lang-javascript.md +269 -0
  267. package/skills/sharp-edges/skills/sharp-edges/references/lang-kotlin.md +265 -0
  268. package/skills/sharp-edges/skills/sharp-edges/references/lang-php.md +245 -0
  269. package/skills/sharp-edges/skills/sharp-edges/references/lang-python.md +274 -0
  270. package/skills/sharp-edges/skills/sharp-edges/references/lang-ruby.md +273 -0
  271. package/skills/sharp-edges/skills/sharp-edges/references/lang-rust.md +272 -0
  272. package/skills/sharp-edges/skills/sharp-edges/references/lang-swift.md +287 -0
  273. package/skills/sharp-edges/skills/sharp-edges/references/language-specific.md +588 -0
  274. package/skills/sherpa-onnx-tts/SKILL.md +103 -0
  275. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +178 -0
  276. package/skills/skill-creator/SKILL.md +370 -0
  277. package/skills/skill-creator/license.txt +202 -0
  278. package/skills/skill-creator/scripts/init_skill.py +378 -0
  279. package/skills/skill-creator/scripts/package_skill.py +111 -0
  280. package/skills/skill-creator/scripts/quick_validate.py +101 -0
  281. package/skills/slack/SKILL.md +144 -0
  282. package/skills/songsee/SKILL.md +49 -0
  283. package/skills/sonoscli/SKILL.md +46 -0
  284. package/skills/spec-to-code-compliance/.claude-plugin/plugin.json +10 -0
  285. package/skills/spec-to-code-compliance/README.md +67 -0
  286. package/skills/spec-to-code-compliance/commands/spec-compliance.md +22 -0
  287. package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/SKILL.md +349 -0
  288. package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/resources/COMPLETENESS_CHECKLIST.md +69 -0
  289. package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/resources/IR_EXAMPLES.md +417 -0
  290. package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/resources/OUTPUT_REQUIREMENTS.md +105 -0
  291. package/skills/spotify-player/SKILL.md +64 -0
  292. package/skills/static-analysis/.claude-plugin/plugin.json +8 -0
  293. package/skills/static-analysis/README.md +59 -0
  294. package/skills/static-analysis/skills/codeql/SKILL.md +315 -0
  295. package/skills/static-analysis/skills/sarif-parsing/SKILL.md +479 -0
  296. package/skills/static-analysis/skills/sarif-parsing/resources/jq-queries.md +162 -0
  297. package/skills/static-analysis/skills/sarif-parsing/resources/sarif_helpers.py +331 -0
  298. package/skills/static-analysis/skills/semgrep/SKILL.md +337 -0
  299. package/skills/summarize/SKILL.md +87 -0
  300. package/skills/testing-handbook-skills/.claude-plugin/plugin.json +8 -0
  301. package/skills/testing-handbook-skills/README.md +241 -0
  302. package/skills/testing-handbook-skills/scripts/pyproject.toml +8 -0
  303. package/skills/testing-handbook-skills/scripts/validate-skills.py +657 -0
  304. package/skills/testing-handbook-skills/skills/address-sanitizer/SKILL.md +341 -0
  305. package/skills/testing-handbook-skills/skills/aflpp/SKILL.md +640 -0
  306. package/skills/testing-handbook-skills/skills/atheris/SKILL.md +515 -0
  307. package/skills/testing-handbook-skills/skills/cargo-fuzz/SKILL.md +454 -0
  308. package/skills/testing-handbook-skills/skills/codeql/SKILL.md +549 -0
  309. package/skills/testing-handbook-skills/skills/constant-time-testing/SKILL.md +507 -0
  310. package/skills/testing-handbook-skills/skills/coverage-analysis/SKILL.md +607 -0
  311. package/skills/testing-handbook-skills/skills/fuzzing-dictionary/SKILL.md +297 -0
  312. package/skills/testing-handbook-skills/skills/fuzzing-obstacles/SKILL.md +426 -0
  313. package/skills/testing-handbook-skills/skills/harness-writing/SKILL.md +614 -0
  314. package/skills/testing-handbook-skills/skills/libafl/SKILL.md +625 -0
  315. package/skills/testing-handbook-skills/skills/libfuzzer/SKILL.md +795 -0
  316. package/skills/testing-handbook-skills/skills/ossfuzz/SKILL.md +426 -0
  317. package/skills/testing-handbook-skills/skills/ruzzy/SKILL.md +443 -0
  318. package/skills/testing-handbook-skills/skills/semgrep/SKILL.md +601 -0
  319. package/skills/testing-handbook-skills/skills/testing-handbook-generator/SKILL.md +372 -0
  320. package/skills/testing-handbook-skills/skills/testing-handbook-generator/agent-prompt.md +280 -0
  321. package/skills/testing-handbook-skills/skills/testing-handbook-generator/discovery.md +452 -0
  322. package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/domain-skill.md +504 -0
  323. package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/fuzzer-skill.md +454 -0
  324. package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/technique-skill.md +527 -0
  325. package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/tool-skill.md +366 -0
  326. package/skills/testing-handbook-skills/skills/testing-handbook-generator/testing.md +482 -0
  327. package/skills/testing-handbook-skills/skills/wycheproof/SKILL.md +533 -0
  328. package/skills/things-mac/SKILL.md +86 -0
  329. package/skills/tmux/SKILL.md +135 -0
  330. package/skills/tmux/scripts/find-sessions.sh +112 -0
  331. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  332. package/skills/trello/SKILL.md +95 -0
  333. package/skills/variant-analysis/.claude-plugin/plugin.json +8 -0
  334. package/skills/variant-analysis/README.md +41 -0
  335. package/skills/variant-analysis/commands/variants.md +23 -0
  336. package/skills/variant-analysis/skills/variant-analysis/METHODOLOGY.md +327 -0
  337. package/skills/variant-analysis/skills/variant-analysis/SKILL.md +142 -0
  338. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/cpp.ql +119 -0
  339. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/go.ql +69 -0
  340. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/java.ql +71 -0
  341. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/javascript.ql +63 -0
  342. package/skills/variant-analysis/skills/variant-analysis/resources/codeql/python.ql +80 -0
  343. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/cpp.yaml +98 -0
  344. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/go.yaml +63 -0
  345. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/java.yaml +61 -0
  346. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/javascript.yaml +60 -0
  347. package/skills/variant-analysis/skills/variant-analysis/resources/semgrep/python.yaml +72 -0
  348. package/skills/variant-analysis/skills/variant-analysis/resources/variant-report-template.md +75 -0
  349. package/skills/video-frames/SKILL.md +46 -0
  350. package/skills/video-frames/scripts/frame.sh +81 -0
  351. package/skills/voice-call/SKILL.md +45 -0
  352. package/skills/wacli/SKILL.md +72 -0
  353. package/skills/weather/SKILL.md +54 -0
  354. package/skills/yara-authoring/.claude-plugin/plugin.json +9 -0
  355. package/skills/yara-authoring/README.md +131 -0
  356. package/skills/yara-authoring/skills/yara-rule-authoring/SKILL.md +645 -0
  357. package/skills/yara-authoring/skills/yara-rule-authoring/examples/MAL_Mac_ProtonRAT_Jan25.yar +99 -0
  358. package/skills/yara-authoring/skills/yara-rule-authoring/examples/MAL_NPM_SupplyChain_Jan25.yar +170 -0
  359. package/skills/yara-authoring/skills/yara-rule-authoring/examples/MAL_Win_Remcos_Jan25.yar +103 -0
  360. package/skills/yara-authoring/skills/yara-rule-authoring/examples/SUSP_CRX_SuspiciousPermissions.yar +134 -0
  361. package/skills/yara-authoring/skills/yara-rule-authoring/examples/SUSP_JS_Obfuscation_Jan25.yar +185 -0
  362. package/skills/yara-authoring/skills/yara-rule-authoring/references/crx-module.md +214 -0
  363. package/skills/yara-authoring/skills/yara-rule-authoring/references/dex-module.md +383 -0
  364. package/skills/yara-authoring/skills/yara-rule-authoring/references/performance.md +333 -0
  365. package/skills/yara-authoring/skills/yara-rule-authoring/references/strings.md +433 -0
  366. package/skills/yara-authoring/skills/yara-rule-authoring/references/style-guide.md +257 -0
  367. package/skills/yara-authoring/skills/yara-rule-authoring/references/testing.md +399 -0
  368. package/skills/yara-authoring/skills/yara-rule-authoring/scripts/atom_analyzer.py +526 -0
  369. package/skills/yara-authoring/skills/yara-rule-authoring/scripts/pyproject.toml +25 -0
  370. package/skills/yara-authoring/skills/yara-rule-authoring/scripts/yara_lint.py +631 -0
  371. package/skills/yara-authoring/skills/yara-rule-authoring/workflows/rule-development.md +493 -0
@@ -0,0 +1,631 @@
1
+ # /// script
2
+ # requires-python = ">=3.11"
3
+ # dependencies = ["yara-x>=0.10.0"]
4
+ # ///
5
+ """YARA-X rule linter for style, metadata, compatibility, and common anti-patterns.
6
+
7
+ Uses the yara-x Python package for actual rule validation, ensuring rules are
8
+ compatible with YARA-X before deployment.
9
+
10
+ Usage:
11
+ uv run yara_lint.py rule.yar
12
+ uv run yara_lint.py --json rules/
13
+ uv run yara_lint.py --strict rule.yar
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import argparse
19
+ import json
20
+ import re
21
+ import sys
22
+ from dataclasses import dataclass
23
+ from dataclasses import field
24
+ from pathlib import Path
25
+ from typing import TYPE_CHECKING
26
+
27
+ import yara_x
28
+
29
+ if TYPE_CHECKING:
30
+ from collections.abc import Iterator
31
+
32
+
33
+ @dataclass
34
+ class Issue:
35
+ """A linting issue."""
36
+
37
+ rule: str
38
+ severity: str # error, warning, info
39
+ code: str
40
+ message: str
41
+ line: int | None = None
42
+
43
+ def to_dict(self) -> dict:
44
+ return {
45
+ "rule": self.rule,
46
+ "severity": self.severity,
47
+ "code": self.code,
48
+ "message": self.message,
49
+ "line": self.line,
50
+ }
51
+
52
+
53
+ @dataclass
54
+ class LintResult:
55
+ """Result of linting a file."""
56
+
57
+ file: str
58
+ issues: list[Issue] = field(default_factory=list)
59
+ parse_error: str | None = None
60
+
61
+ @property
62
+ def error_count(self) -> int:
63
+ return sum(1 for i in self.issues if i.severity == "error")
64
+
65
+ @property
66
+ def warning_count(self) -> int:
67
+ return sum(1 for i in self.issues if i.severity == "warning")
68
+
69
+
70
+ # Naming convention patterns
71
+ VALID_CATEGORY_PREFIXES = frozenset(
72
+ {
73
+ "MAL",
74
+ "HKTL",
75
+ "WEBSHELL",
76
+ "EXPL",
77
+ "VULN",
78
+ "SUSP",
79
+ "PUA",
80
+ "GEN",
81
+ "APT",
82
+ "CRIME",
83
+ "RANSOM",
84
+ "RAT",
85
+ "MINER",
86
+ "STEALER",
87
+ "LOADER",
88
+ "C2",
89
+ }
90
+ )
91
+
92
+ VALID_PLATFORM_INDICATORS = frozenset(
93
+ {
94
+ "Win",
95
+ "Lnx",
96
+ "Mac",
97
+ "Android",
98
+ "iOS",
99
+ "Multi",
100
+ "PE",
101
+ "ELF",
102
+ "PS",
103
+ "DOC",
104
+ "PDF",
105
+ "JAR",
106
+ "CRX",
107
+ }
108
+ )
109
+
110
+ # Common FP-prone strings to warn about
111
+ FP_PRONE_STRINGS = frozenset(
112
+ {
113
+ "cmd.exe",
114
+ "powershell.exe",
115
+ "explorer.exe",
116
+ "notepad.exe",
117
+ "VirtualAlloc",
118
+ "VirtualProtect",
119
+ "CreateRemoteThread",
120
+ "WriteProcessMemory",
121
+ "ReadProcessMemory",
122
+ "NtCreateThread",
123
+ "KERNEL32.dll",
124
+ "ntdll.dll",
125
+ "USER32.dll",
126
+ "ADVAPI32.dll",
127
+ "C:\\Windows",
128
+ "C:\\Windows\\System32",
129
+ "%s",
130
+ "%d",
131
+ "%x",
132
+ "%08x",
133
+ "http://",
134
+ "https://",
135
+ }
136
+ )
137
+
138
+ # Deprecated features
139
+ DEPRECATED_PATTERNS = {
140
+ "entrypoint": "Use pe.entry_point instead of deprecated entrypoint",
141
+ "PEiD": "PEiD-style signatures are obsolete; use modern detection",
142
+ }
143
+
144
+
145
+ def check_naming_convention(rule_name: str) -> Iterator[Issue]:
146
+ """Check if rule name follows the style guide convention."""
147
+ parts = rule_name.split("_")
148
+
149
+ if len(parts) < 3:
150
+ yield Issue(
151
+ rule=rule_name,
152
+ severity="warning",
153
+ code="W001",
154
+ message=f"Rule name '{rule_name}' should follow CATEGORY_PLATFORM_FAMILY_DATE format",
155
+ )
156
+ return
157
+
158
+ # Check category prefix
159
+ if parts[0] not in VALID_CATEGORY_PREFIXES:
160
+ valid = ", ".join(sorted(VALID_CATEGORY_PREFIXES))
161
+ yield Issue(
162
+ rule=rule_name,
163
+ severity="info",
164
+ code="I001",
165
+ message=f"Unrecognized category prefix '{parts[0]}'; expected one of: {valid}",
166
+ )
167
+
168
+
169
+ def extract_metadata(content: str, rule_name: str) -> dict[str, str]:
170
+ """Extract metadata from a rule using regex (since yara-x doesn't expose parsed AST)."""
171
+ metadata = {}
172
+
173
+ # Find the rule block
174
+ rule_pattern = rf"rule\s+{re.escape(rule_name)}\s*\{{"
175
+ rule_match = re.search(rule_pattern, content)
176
+ if not rule_match:
177
+ return metadata
178
+
179
+ # Find meta: section within the rule
180
+ start = rule_match.end()
181
+ # Find matching closing brace
182
+ brace_count = 1
183
+ pos = start
184
+ while pos < len(content) and brace_count > 0:
185
+ if content[pos] == "{":
186
+ brace_count += 1
187
+ elif content[pos] == "}":
188
+ brace_count -= 1
189
+ pos += 1
190
+
191
+ rule_content = content[start : pos - 1]
192
+
193
+ # Extract meta section
194
+ pattern = r"meta\s*:\s*(.*?)(?=strings\s*:|condition\s*:|$)"
195
+ meta_match = re.search(pattern, rule_content, re.DOTALL)
196
+ if meta_match:
197
+ meta_section = meta_match.group(1)
198
+ # Parse key = "value" pairs
199
+ for match in re.finditer(r'(\w+)\s*=\s*"([^"]*)"', meta_section):
200
+ metadata[match.group(1)] = match.group(2)
201
+
202
+ return metadata
203
+
204
+
205
+ def extract_strings(content: str, rule_name: str) -> list[dict]:
206
+ """Extract strings from a rule using regex."""
207
+ strings = []
208
+
209
+ # Find the rule block
210
+ rule_pattern = rf"rule\s+{re.escape(rule_name)}\s*\{{"
211
+ rule_match = re.search(rule_pattern, content)
212
+ if not rule_match:
213
+ return strings
214
+
215
+ # Find strings section
216
+ start = rule_match.end()
217
+ brace_count = 1
218
+ pos = start
219
+ while pos < len(content) and brace_count > 0:
220
+ if content[pos] == "{":
221
+ brace_count += 1
222
+ elif content[pos] == "}":
223
+ brace_count -= 1
224
+ pos += 1
225
+
226
+ rule_content = content[start : pos - 1]
227
+
228
+ strings_match = re.search(r"strings\s*:\s*(.*?)(?=condition\s*:|$)", rule_content, re.DOTALL)
229
+ if not strings_match:
230
+ return strings
231
+
232
+ strings_section = strings_match.group(1)
233
+
234
+ # Parse text strings: $name = "value" modifiers
235
+ for match in re.finditer(r'(\$\w+)\s*=\s*"([^"]*)"([^\n]*)', strings_section):
236
+ modifiers = match.group(3).strip().split()
237
+ strings.append(
238
+ {
239
+ "name": match.group(1),
240
+ "value": match.group(2),
241
+ "type": "text",
242
+ "modifiers": modifiers,
243
+ }
244
+ )
245
+
246
+ # Parse hex strings: $name = { hex }
247
+ for match in re.finditer(r"(\$\w+)\s*=\s*\{([^}]*)\}", strings_section):
248
+ strings.append(
249
+ {
250
+ "name": match.group(1),
251
+ "value": match.group(2).strip(),
252
+ "type": "byte",
253
+ "modifiers": [],
254
+ }
255
+ )
256
+
257
+ # Parse regex strings: $name = /pattern/ modifiers
258
+ for match in re.finditer(r"(\$\w+)\s*=\s*/([^/]*)/([^\n]*)", strings_section):
259
+ modifiers = match.group(3).strip().split()
260
+ strings.append(
261
+ {
262
+ "name": match.group(1),
263
+ "value": match.group(2),
264
+ "type": "regex",
265
+ "modifiers": modifiers,
266
+ }
267
+ )
268
+
269
+ return strings
270
+
271
+
272
+ def check_metadata(rule_name: str, metadata: dict[str, str]) -> Iterator[Issue]:
273
+ """Check for required and well-formed metadata."""
274
+ # Required fields
275
+ required = ["description", "author", "date"]
276
+ for field_name in required:
277
+ if field_name not in metadata:
278
+ yield Issue(
279
+ rule=rule_name,
280
+ severity="error",
281
+ code="E001",
282
+ message=f"Missing required metadata field: {field_name}",
283
+ )
284
+
285
+ # Description checks
286
+ if "description" in metadata:
287
+ desc = metadata["description"]
288
+ if not desc.startswith("Detects"):
289
+ yield Issue(
290
+ rule=rule_name,
291
+ severity="warning",
292
+ code="W002",
293
+ message="Description should start with 'Detects'",
294
+ )
295
+ if len(desc) < 60:
296
+ yield Issue(
297
+ rule=rule_name,
298
+ severity="warning",
299
+ code="W003",
300
+ message=f"Description too short ({len(desc)} chars); aim for 60-400 characters",
301
+ )
302
+ if len(desc) > 400:
303
+ yield Issue(
304
+ rule=rule_name,
305
+ severity="info",
306
+ code="I002",
307
+ message=f"Description quite long ({len(desc)} chars); consider trimming to <400",
308
+ )
309
+
310
+ # Reference check
311
+ if "reference" not in metadata:
312
+ yield Issue(
313
+ rule=rule_name,
314
+ severity="warning",
315
+ code="W004",
316
+ message="Missing 'reference' metadata; add URL to analysis or source",
317
+ )
318
+
319
+
320
+ def check_strings(rule_name: str, strings: list[dict]) -> Iterator[Issue]:
321
+ """Check strings for anti-patterns and quality issues."""
322
+ for string in strings:
323
+ string_id = string.get("name", "unknown")
324
+ string_value = string.get("value", "")
325
+ string_type = string.get("type", "text")
326
+ modifiers = string.get("modifiers", [])
327
+
328
+ # Check string length (text strings)
329
+ if string_type == "text":
330
+ if len(string_value) < 4:
331
+ yield Issue(
332
+ rule=rule_name,
333
+ severity="error",
334
+ code="E002",
335
+ message=f"String {string_id} is only {len(string_value)} bytes; "
336
+ "minimum 4 bytes for good atoms",
337
+ )
338
+
339
+ # Check for FP-prone strings
340
+ for fp_string in FP_PRONE_STRINGS:
341
+ if fp_string.lower() in string_value.lower():
342
+ yield Issue(
343
+ rule=rule_name,
344
+ severity="warning",
345
+ code="W005",
346
+ message=f"String {string_id} contains FP-prone pattern '{fp_string}'",
347
+ )
348
+
349
+ # YARA-X specific: base64 modifier requires 3+ chars
350
+ if "base64" in modifiers and len(string_value) < 3:
351
+ yield Issue(
352
+ rule=rule_name,
353
+ severity="error",
354
+ code="E006",
355
+ message=f"String {string_id} uses 'base64' but is only {len(string_value)} "
356
+ "chars; YARA-X requires 3+ characters for base64 modifier",
357
+ )
358
+
359
+ # Check hex strings
360
+ if string_type == "byte":
361
+ hex_value = string_value
362
+ # Count actual bytes (excluding wildcards and spaces)
363
+ byte_count = len(re.findall(r"[0-9A-Fa-f]{2}", hex_value))
364
+ if byte_count < 4:
365
+ yield Issue(
366
+ rule=rule_name,
367
+ severity="error",
368
+ code="E003",
369
+ message=f"Hex string {string_id} has only {byte_count} bytes; "
370
+ "minimum 4 for good atoms",
371
+ )
372
+
373
+ # Check for too many wildcards at start
374
+ if re.match(r"^\s*\?\?", hex_value):
375
+ yield Issue(
376
+ rule=rule_name,
377
+ severity="warning",
378
+ code="W006",
379
+ message=f"Hex string {string_id} starts with wildcard; "
380
+ "move fixed bytes first for better atoms",
381
+ )
382
+
383
+ # Check regex strings for YARA-X compatibility issues
384
+ if string_type == "regex":
385
+ # Check for unescaped { in regex (YARA-X strict mode)
386
+ if re.search(r"(?<!\\)\{(?![0-9])", string_value):
387
+ yield Issue(
388
+ rule=rule_name,
389
+ severity="error",
390
+ code="E007",
391
+ message=f"Regex {string_id} has unescaped '{{'; "
392
+ "YARA-X requires escaping as '\\{{'",
393
+ )
394
+
395
+ # Check for unbounded regex
396
+ if re.search(r"(?<!\\)\.\*(?!\?)", string_value) or re.search(
397
+ r"(?<!\\)\.\+(?!\?)", string_value
398
+ ):
399
+ yield Issue(
400
+ rule=rule_name,
401
+ severity="warning",
402
+ code="W008",
403
+ message=f"Regex {string_id} has unbounded quantifier (.*/.+); "
404
+ "use bounded quantifiers {{1,N}}",
405
+ )
406
+
407
+
408
+ def check_string_modifiers(rule_name: str, strings: list[dict]) -> Iterator[Issue]:
409
+ """Check string modifiers for performance concerns."""
410
+ for string in strings:
411
+ string_id = string.get("name", "unknown")
412
+ modifiers = string.get("modifiers", [])
413
+ value = string.get("value", "")
414
+
415
+ # nocase on long strings
416
+ if "nocase" in modifiers and len(value) > 20:
417
+ yield Issue(
418
+ rule=rule_name,
419
+ severity="info",
420
+ code="I003",
421
+ message=f"String {string_id} uses 'nocase' on long string; performance impact",
422
+ )
423
+
424
+ # xor without range
425
+ if "xor" in modifiers and not any("xor(" in str(m) for m in modifiers):
426
+ yield Issue(
427
+ rule=rule_name,
428
+ severity="info",
429
+ code="I004",
430
+ message=f"String {string_id} uses 'xor' without range; generates 255 patterns",
431
+ )
432
+
433
+
434
+ def check_condition(rule_name: str, content: str) -> Iterator[Issue]:
435
+ """Check condition for performance and deprecated features."""
436
+ # Find the rule's condition
437
+ rule_pattern = rf"rule\s+{re.escape(rule_name)}\s*\{{"
438
+ rule_match = re.search(rule_pattern, content)
439
+ if not rule_match:
440
+ return
441
+
442
+ start = rule_match.end()
443
+ brace_count = 1
444
+ pos = start
445
+ while pos < len(content) and brace_count > 0:
446
+ if content[pos] == "{":
447
+ brace_count += 1
448
+ elif content[pos] == "}":
449
+ brace_count -= 1
450
+ pos += 1
451
+
452
+ rule_content = content[start : pos - 1]
453
+
454
+ condition_match = re.search(r"condition\s*:\s*(.*)", rule_content, re.DOTALL)
455
+ if not condition_match:
456
+ return
457
+
458
+ condition_str = condition_match.group(1).strip()
459
+
460
+ # Check for deprecated features
461
+ for pattern, message in DEPRECATED_PATTERNS.items():
462
+ if pattern.lower() in condition_str.lower():
463
+ yield Issue(
464
+ rule=rule_name,
465
+ severity="warning",
466
+ code="W007",
467
+ message=message,
468
+ )
469
+
470
+ # Check for negative array indexing (not supported in YARA-X)
471
+ if re.search(r"@\w+\s*\[\s*-\d+\s*\]", condition_str):
472
+ yield Issue(
473
+ rule=rule_name,
474
+ severity="error",
475
+ code="E008",
476
+ message="Negative array indexing (e.g., @a[-1]) not supported in YARA-X; "
477
+ "use @a[#a - 1] instead",
478
+ )
479
+
480
+
481
+ def extract_rule_names(content: str) -> list[str]:
482
+ """Extract rule names from YARA source."""
483
+ return re.findall(r"(?:private\s+)?rule\s+(\w+)\s*[:{]", content)
484
+
485
+
486
+ def lint_file(file_path: Path) -> LintResult:
487
+ """Lint a YARA file using yara-x for validation."""
488
+ result = LintResult(file=str(file_path))
489
+
490
+ try:
491
+ content = file_path.read_text()
492
+ except OSError as e:
493
+ result.parse_error = f"Cannot read file: {e}"
494
+ return result
495
+
496
+ # First, try to compile with yara-x to catch syntax/compatibility errors
497
+ try:
498
+ compiler = yara_x.Compiler()
499
+ compiler.add_source(content)
500
+ compiler.build()
501
+ except yara_x.CompileError as e:
502
+ # Extract useful information from the error
503
+ error_msg = str(e)
504
+ result.issues.append(
505
+ Issue(
506
+ rule="(compilation)",
507
+ severity="error",
508
+ code="E000",
509
+ message=f"YARA-X compilation error: {error_msg}",
510
+ )
511
+ )
512
+ # Still try to do style checks even if compilation fails
513
+
514
+ # Extract rule names and perform style checks
515
+ rule_names = extract_rule_names(content)
516
+
517
+ for rule_name in rule_names:
518
+ result.issues.extend(check_naming_convention(rule_name))
519
+
520
+ metadata = extract_metadata(content, rule_name)
521
+ result.issues.extend(check_metadata(rule_name, metadata))
522
+
523
+ strings = extract_strings(content, rule_name)
524
+ result.issues.extend(check_strings(rule_name, strings))
525
+ result.issues.extend(check_string_modifiers(rule_name, strings))
526
+
527
+ result.issues.extend(check_condition(rule_name, content))
528
+
529
+ return result
530
+
531
+
532
+ def lint_directory(dir_path: Path) -> list[LintResult]:
533
+ """Lint all YARA files in a directory."""
534
+ results = []
535
+ for yar_file in dir_path.rglob("*.yar"):
536
+ results.append(lint_file(yar_file))
537
+ for yar_file in dir_path.rglob("*.yara"):
538
+ results.append(lint_file(yar_file))
539
+ return results
540
+
541
+
542
+ def format_result(result: LintResult, *, use_color: bool = True) -> str:
543
+ """Format a lint result for terminal output."""
544
+ lines = []
545
+
546
+ if use_color:
547
+ red = "\033[91m"
548
+ yellow = "\033[93m"
549
+ blue = "\033[94m"
550
+ reset = "\033[0m"
551
+ bold = "\033[1m"
552
+ else:
553
+ red = yellow = blue = reset = bold = ""
554
+
555
+ if result.parse_error:
556
+ lines.append(f"{bold}{result.file}{reset}")
557
+ lines.append(f" {red}ERROR{reset}: {result.parse_error}")
558
+ return "\n".join(lines)
559
+
560
+ if not result.issues:
561
+ return ""
562
+
563
+ lines.append(f"{bold}{result.file}{reset}")
564
+
565
+ for issue in result.issues:
566
+ if issue.severity == "error":
567
+ color = red
568
+ elif issue.severity == "warning":
569
+ color = yellow
570
+ else:
571
+ color = blue
572
+
573
+ severity_upper = issue.severity.upper()
574
+ line_info = f":{issue.line}" if issue.line else ""
575
+ msg = f" {color}{severity_upper}{reset} [{issue.code}] "
576
+ msg += f"{issue.rule}{line_info}: {issue.message}"
577
+ lines.append(msg)
578
+
579
+ return "\n".join(lines)
580
+
581
+
582
+ def main() -> int:
583
+ parser = argparse.ArgumentParser(description="YARA-X rule linter")
584
+ parser.add_argument("path", type=Path, help="File or directory to lint")
585
+ parser.add_argument("--json", action="store_true", help="Output JSON format")
586
+ parser.add_argument("--strict", action="store_true", help="Treat warnings as errors")
587
+ parser.add_argument("--no-color", action="store_true", help="Disable colored output")
588
+ args = parser.parse_args()
589
+
590
+ if args.path.is_file():
591
+ results = [lint_file(args.path)]
592
+ elif args.path.is_dir():
593
+ results = lint_directory(args.path)
594
+ else:
595
+ print(f"Error: {args.path} does not exist", file=sys.stderr)
596
+ return 1
597
+
598
+ if args.json:
599
+ output = {
600
+ "results": [
601
+ {
602
+ "file": r.file,
603
+ "parse_error": r.parse_error,
604
+ "issues": [i.to_dict() for i in r.issues],
605
+ }
606
+ for r in results
607
+ ]
608
+ }
609
+ print(json.dumps(output, indent=2))
610
+ else:
611
+ use_color = not args.no_color and sys.stdout.isatty()
612
+ for result in results:
613
+ formatted = format_result(result, use_color=use_color)
614
+ if formatted:
615
+ print(formatted)
616
+ print()
617
+
618
+ # Calculate exit code
619
+ total_errors = sum(r.error_count for r in results)
620
+ total_warnings = sum(r.warning_count for r in results)
621
+ parse_errors = sum(1 for r in results if r.parse_error)
622
+
623
+ if parse_errors > 0 or total_errors > 0:
624
+ return 1
625
+ if args.strict and total_warnings > 0:
626
+ return 1
627
+ return 0
628
+
629
+
630
+ if __name__ == "__main__":
631
+ sys.exit(main())