@vigolium/piolium 0.0.1

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 (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +117 -0
  3. package/agents/access-auditor.md +300 -0
  4. package/agents/assumption-breaker.md +154 -0
  5. package/agents/attack-designer.md +116 -0
  6. package/agents/code-scanner.md +139 -0
  7. package/agents/concurrency-auditor.md +238 -0
  8. package/agents/confirm-writer.md +257 -0
  9. package/agents/context-reviewer.md +274 -0
  10. package/agents/cross-verifier.md +165 -0
  11. package/agents/cve-scout.md +381 -0
  12. package/agents/env-builder.md +282 -0
  13. package/agents/env-profiler.md +205 -0
  14. package/agents/evidence-collector.md +140 -0
  15. package/agents/finding-grader.md +142 -0
  16. package/agents/finding-writer.md +148 -0
  17. package/agents/flow-tracer.md +106 -0
  18. package/agents/goal-backtracer.md +146 -0
  19. package/agents/history-miner.md +467 -0
  20. package/agents/independent-verifier.md +118 -0
  21. package/agents/intent-mapper.md +183 -0
  22. package/agents/longshot-collector.md +128 -0
  23. package/agents/longshot-prober.md +126 -0
  24. package/agents/patch-auditor.md +73 -0
  25. package/agents/poc-author.md +124 -0
  26. package/agents/poc-runner.md +194 -0
  27. package/agents/probe-lead.md +269 -0
  28. package/agents/red-challenger.md +101 -0
  29. package/agents/report-composer.md +208 -0
  30. package/agents/review-adjudicator.md +216 -0
  31. package/agents/spec-auditor.md +155 -0
  32. package/agents/taint-tracer.md +265 -0
  33. package/agents/test-locator.md +209 -0
  34. package/agents/threat-modeler.md +132 -0
  35. package/agents/variant-scanner.md +108 -0
  36. package/agents/variant-spotter.md +110 -0
  37. package/bin/piolium.mjs +376 -0
  38. package/extensions/piolium/_vendor/yaml.bundle.d.mts +6 -0
  39. package/extensions/piolium/_vendor/yaml.bundle.mjs +139 -0
  40. package/extensions/piolium/agent-runner.ts +322 -0
  41. package/extensions/piolium/agents.ts +266 -0
  42. package/extensions/piolium/audit-state.ts +522 -0
  43. package/extensions/piolium/bundled-resources.ts +97 -0
  44. package/extensions/piolium/candidate-scan.ts +966 -0
  45. package/extensions/piolium/command-target.ts +177 -0
  46. package/extensions/piolium/console-stream.ts +57 -0
  47. package/extensions/piolium/export-results.ts +380 -0
  48. package/extensions/piolium/findings.ts +448 -0
  49. package/extensions/piolium/heartbeat.ts +182 -0
  50. package/extensions/piolium/help.ts +234 -0
  51. package/extensions/piolium/index.ts +1865 -0
  52. package/extensions/piolium/longshot.ts +530 -0
  53. package/extensions/piolium/matcher-suggestions.ts +196 -0
  54. package/extensions/piolium/matcher-utils.ts +83 -0
  55. package/extensions/piolium/modes/balanced.ts +750 -0
  56. package/extensions/piolium/modes/confirm-bootstrap.ts +186 -0
  57. package/extensions/piolium/modes/confirm.ts +697 -0
  58. package/extensions/piolium/modes/deep.ts +917 -0
  59. package/extensions/piolium/modes/diff.ts +177 -0
  60. package/extensions/piolium/modes/lite.ts +540 -0
  61. package/extensions/piolium/modes/longshot.ts +595 -0
  62. package/extensions/piolium/modes/merge.ts +204 -0
  63. package/extensions/piolium/modes/phase-runner.ts +267 -0
  64. package/extensions/piolium/modes/reinvest.ts +546 -0
  65. package/extensions/piolium/modes/revisit.ts +279 -0
  66. package/extensions/piolium/modes.ts +48 -0
  67. package/extensions/piolium/phase-labels.ts +123 -0
  68. package/extensions/piolium/phase-status-strip.ts +92 -0
  69. package/extensions/piolium/prompt-prefix-editor.ts +39 -0
  70. package/extensions/piolium/providers/anthropic-vertex.ts +836 -0
  71. package/extensions/piolium/recon.ts +409 -0
  72. package/extensions/piolium/result-stats.ts +105 -0
  73. package/extensions/piolium/retry.ts +120 -0
  74. package/extensions/piolium/scheduler.ts +212 -0
  75. package/extensions/piolium/secrets.ts +368 -0
  76. package/extensions/piolium/tools/web-tools.ts +148 -0
  77. package/package.json +77 -0
  78. package/skills/agentic-actions-auditor/SKILL.md +327 -0
  79. package/skills/agentic-actions-auditor/references/action-profiles.md +186 -0
  80. package/skills/agentic-actions-auditor/references/cross-file-resolution.md +209 -0
  81. package/skills/agentic-actions-auditor/references/foundations.md +94 -0
  82. package/skills/agentic-actions-auditor/references/vector-a-env-var-intermediary.md +77 -0
  83. package/skills/agentic-actions-auditor/references/vector-b-direct-expression-injection.md +83 -0
  84. package/skills/agentic-actions-auditor/references/vector-c-cli-data-fetch.md +83 -0
  85. package/skills/agentic-actions-auditor/references/vector-d-pr-target-checkout.md +88 -0
  86. package/skills/agentic-actions-auditor/references/vector-e-error-log-injection.md +88 -0
  87. package/skills/agentic-actions-auditor/references/vector-f-subshell-expansion.md +82 -0
  88. package/skills/agentic-actions-auditor/references/vector-g-eval-of-ai-output.md +91 -0
  89. package/skills/agentic-actions-auditor/references/vector-h-dangerous-sandbox-configs.md +102 -0
  90. package/skills/agentic-actions-auditor/references/vector-i-wildcard-allowlists.md +88 -0
  91. package/skills/audit/SKILL.md +562 -0
  92. package/skills/audit/assets/icon.svg +7 -0
  93. package/skills/audit/hooks/scripts/validate_phase_output.py +550 -0
  94. package/skills/audit/references/adversarial-review.md +148 -0
  95. package/skills/audit/references/architecture-aware-sast.md +306 -0
  96. package/skills/audit/references/audit-workflow.md +737 -0
  97. package/skills/audit/references/chamber-protocol.md +384 -0
  98. package/skills/audit/references/creative-attack-modes.md +221 -0
  99. package/skills/audit/references/deep-analysis.md +273 -0
  100. package/skills/audit/references/domain-attack-playbooks.md +1129 -0
  101. package/skills/audit/references/knowledge-base-template.md +513 -0
  102. package/skills/audit/references/real-env-validation.md +191 -0
  103. package/skills/audit/references/report-templates.md +417 -0
  104. package/skills/audit/references/triage-and-prereqs.md +134 -0
  105. package/skills/audit/scripts/consolidate_drafts.py +554 -0
  106. package/skills/audit/scripts/partition_findings.py +152 -0
  107. package/skills/audit/scripts/rg-hotspots.sh +121 -0
  108. package/skills/audit/scripts/stamp_file_state.py +349 -0
  109. package/skills/code-reviewer/SKILL.md +65 -0
  110. package/skills/codeql/SKILL.md +281 -0
  111. package/skills/codeql/references/build-fixes.md +90 -0
  112. package/skills/codeql/references/diagnostic-query-templates.md +339 -0
  113. package/skills/codeql/references/extension-yaml-format.md +209 -0
  114. package/skills/codeql/references/important-only-suite.md +153 -0
  115. package/skills/codeql/references/language-details.md +207 -0
  116. package/skills/codeql/references/macos-arm64e-workaround.md +179 -0
  117. package/skills/codeql/references/performance-tuning.md +111 -0
  118. package/skills/codeql/references/quality-assessment.md +172 -0
  119. package/skills/codeql/references/ruleset-catalog.md +63 -0
  120. package/skills/codeql/references/run-all-suite.md +92 -0
  121. package/skills/codeql/references/sarif-processing.md +79 -0
  122. package/skills/codeql/references/threat-models.md +51 -0
  123. package/skills/codeql/workflows/build-database.md +280 -0
  124. package/skills/codeql/workflows/create-data-extensions.md +261 -0
  125. package/skills/codeql/workflows/run-analysis.md +301 -0
  126. package/skills/differential-review/SKILL.md +220 -0
  127. package/skills/differential-review/adversarial.md +203 -0
  128. package/skills/differential-review/methodology.md +234 -0
  129. package/skills/differential-review/patterns.md +300 -0
  130. package/skills/differential-review/reporting.md +369 -0
  131. package/skills/fp-check/SKILL.md +125 -0
  132. package/skills/fp-check/references/bug-class-verification.md +114 -0
  133. package/skills/fp-check/references/deep-verification.md +143 -0
  134. package/skills/fp-check/references/evidence-templates.md +91 -0
  135. package/skills/fp-check/references/false-positive-patterns.md +115 -0
  136. package/skills/fp-check/references/gate-reviews.md +27 -0
  137. package/skills/fp-check/references/standard-verification.md +78 -0
  138. package/skills/insecure-defaults/SKILL.md +117 -0
  139. package/skills/insecure-defaults/references/examples.md +409 -0
  140. package/skills/last30days/SKILL.md +444 -0
  141. package/skills/sarif-parsing/SKILL.md +483 -0
  142. package/skills/sarif-parsing/resources/jq-queries.md +162 -0
  143. package/skills/sarif-parsing/resources/sarif_helpers.py +331 -0
  144. package/skills/security-threat-model/LICENSE.txt +201 -0
  145. package/skills/security-threat-model/SKILL.md +81 -0
  146. package/skills/security-threat-model/agents/openai.yaml +4 -0
  147. package/skills/security-threat-model/references/prompt-template.md +255 -0
  148. package/skills/security-threat-model/references/security-controls-and-assets.md +32 -0
  149. package/skills/semgrep/SKILL.md +212 -0
  150. package/skills/semgrep/references/rulesets.md +162 -0
  151. package/skills/semgrep/references/scan-modes.md +110 -0
  152. package/skills/semgrep/references/scanner-task-prompt.md +140 -0
  153. package/skills/semgrep/scripts/merge_sarif.py +203 -0
  154. package/skills/semgrep/workflows/scan-workflow.md +311 -0
  155. package/skills/semgrep-rule-creator/SKILL.md +168 -0
  156. package/skills/semgrep-rule-creator/references/quick-reference.md +202 -0
  157. package/skills/semgrep-rule-creator/references/workflow.md +240 -0
  158. package/skills/semgrep-rule-variant-creator/SKILL.md +205 -0
  159. package/skills/semgrep-rule-variant-creator/references/applicability-analysis.md +250 -0
  160. package/skills/semgrep-rule-variant-creator/references/language-syntax-guide.md +324 -0
  161. package/skills/semgrep-rule-variant-creator/references/workflow.md +518 -0
  162. package/skills/sharp-edges/SKILL.md +292 -0
  163. package/skills/sharp-edges/references/auth-patterns.md +252 -0
  164. package/skills/sharp-edges/references/case-studies.md +274 -0
  165. package/skills/sharp-edges/references/config-patterns.md +333 -0
  166. package/skills/sharp-edges/references/crypto-apis.md +190 -0
  167. package/skills/sharp-edges/references/lang-c.md +205 -0
  168. package/skills/sharp-edges/references/lang-csharp.md +285 -0
  169. package/skills/sharp-edges/references/lang-go.md +270 -0
  170. package/skills/sharp-edges/references/lang-java.md +263 -0
  171. package/skills/sharp-edges/references/lang-javascript.md +269 -0
  172. package/skills/sharp-edges/references/lang-kotlin.md +265 -0
  173. package/skills/sharp-edges/references/lang-php.md +245 -0
  174. package/skills/sharp-edges/references/lang-python.md +274 -0
  175. package/skills/sharp-edges/references/lang-ruby.md +273 -0
  176. package/skills/sharp-edges/references/lang-rust.md +272 -0
  177. package/skills/sharp-edges/references/lang-swift.md +287 -0
  178. package/skills/sharp-edges/references/language-specific.md +588 -0
  179. package/skills/spec-to-code-compliance/SKILL.md +357 -0
  180. package/skills/spec-to-code-compliance/resources/COMPLETENESS_CHECKLIST.md +69 -0
  181. package/skills/spec-to-code-compliance/resources/IR_EXAMPLES.md +417 -0
  182. package/skills/spec-to-code-compliance/resources/OUTPUT_REQUIREMENTS.md +105 -0
  183. package/skills/supply-chain-risk-auditor/SKILL.md +67 -0
  184. package/skills/supply-chain-risk-auditor/resources/results-template.md +41 -0
  185. package/skills/variant-analysis/METHODOLOGY.md +327 -0
  186. package/skills/variant-analysis/SKILL.md +142 -0
  187. package/skills/variant-analysis/resources/codeql/cpp.ql +119 -0
  188. package/skills/variant-analysis/resources/codeql/go.ql +69 -0
  189. package/skills/variant-analysis/resources/codeql/java.ql +71 -0
  190. package/skills/variant-analysis/resources/codeql/javascript.ql +63 -0
  191. package/skills/variant-analysis/resources/codeql/python.ql +80 -0
  192. package/skills/variant-analysis/resources/semgrep/cpp.yaml +98 -0
  193. package/skills/variant-analysis/resources/semgrep/go.yaml +63 -0
  194. package/skills/variant-analysis/resources/semgrep/java.yaml +61 -0
  195. package/skills/variant-analysis/resources/semgrep/javascript.yaml +60 -0
  196. package/skills/variant-analysis/resources/semgrep/python.yaml +72 -0
  197. package/skills/variant-analysis/resources/variant-report-template.md +75 -0
  198. package/skills/vuln-report/SKILL.md +137 -0
  199. package/skills/vuln-report/agents/openai.yaml +4 -0
  200. package/skills/vuln-report/references/report-template.md +135 -0
  201. package/skills/wooyun-legacy/SKILL.md +367 -0
  202. package/skills/wooyun-legacy/references/bank-penetration.md +222 -0
  203. package/skills/wooyun-legacy/references/checklists/command-execution-checklist.md +119 -0
  204. package/skills/wooyun-legacy/references/checklists/csrf-checklist.md +74 -0
  205. package/skills/wooyun-legacy/references/checklists/file-upload-checklist.md +108 -0
  206. package/skills/wooyun-legacy/references/checklists/info-disclosure-checklist.md +114 -0
  207. package/skills/wooyun-legacy/references/checklists/logic-flaws-checklist.md +95 -0
  208. package/skills/wooyun-legacy/references/checklists/misconfig-checklist.md +124 -0
  209. package/skills/wooyun-legacy/references/checklists/path-traversal-checklist.md +87 -0
  210. package/skills/wooyun-legacy/references/checklists/rce-checklist.md +93 -0
  211. package/skills/wooyun-legacy/references/checklists/sql-injection-checklist.md +97 -0
  212. package/skills/wooyun-legacy/references/checklists/ssrf-checklist.md +99 -0
  213. package/skills/wooyun-legacy/references/checklists/unauthorized-access-checklist.md +89 -0
  214. package/skills/wooyun-legacy/references/checklists/weak-password-checklist.md +115 -0
  215. package/skills/wooyun-legacy/references/checklists/xss-checklist.md +103 -0
  216. package/skills/wooyun-legacy/references/checklists/xxe-checklist.md +130 -0
  217. package/skills/wooyun-legacy/references/info-disclosure.md +975 -0
  218. package/skills/wooyun-legacy/references/logic-flaws.md +721 -0
  219. package/skills/wooyun-legacy/references/path-traversal.md +1191 -0
  220. package/skills/wooyun-legacy/references/telecom-penetration.md +156 -0
  221. package/skills/wooyun-legacy/references/unauthorized-access.md +980 -0
  222. package/skills/wooyun-legacy/references/xss.md +746 -0
  223. package/skills/zeroize-audit/SKILL.md +371 -0
  224. package/skills/zeroize-audit/configs/c.yaml +21 -0
  225. package/skills/zeroize-audit/configs/default.yaml +128 -0
  226. package/skills/zeroize-audit/configs/rust.yaml +83 -0
  227. package/skills/zeroize-audit/prompts/report_template.md +238 -0
  228. package/skills/zeroize-audit/prompts/system.md +163 -0
  229. package/skills/zeroize-audit/prompts/task.md +97 -0
  230. package/skills/zeroize-audit/references/compile-commands.md +231 -0
  231. package/skills/zeroize-audit/references/detection-strategy.md +191 -0
  232. package/skills/zeroize-audit/references/ir-analysis.md +252 -0
  233. package/skills/zeroize-audit/references/mcp-analysis.md +221 -0
  234. package/skills/zeroize-audit/references/poc-generation.md +470 -0
  235. package/skills/zeroize-audit/references/rust-zeroization-patterns.md +867 -0
  236. package/skills/zeroize-audit/schemas/input.json +83 -0
  237. package/skills/zeroize-audit/schemas/output.json +140 -0
  238. package/skills/zeroize-audit/tools/analyze_asm.sh +202 -0
  239. package/skills/zeroize-audit/tools/analyze_cfg.py +381 -0
  240. package/skills/zeroize-audit/tools/analyze_heap.sh +211 -0
  241. package/skills/zeroize-audit/tools/analyze_ir_semantic.py +429 -0
  242. package/skills/zeroize-audit/tools/diff_ir.sh +135 -0
  243. package/skills/zeroize-audit/tools/diff_rust_mir.sh +189 -0
  244. package/skills/zeroize-audit/tools/emit_asm.sh +67 -0
  245. package/skills/zeroize-audit/tools/emit_ir.sh +77 -0
  246. package/skills/zeroize-audit/tools/emit_rust_asm.sh +178 -0
  247. package/skills/zeroize-audit/tools/emit_rust_ir.sh +150 -0
  248. package/skills/zeroize-audit/tools/emit_rust_mir.sh +158 -0
  249. package/skills/zeroize-audit/tools/extract_compile_flags.py +284 -0
  250. package/skills/zeroize-audit/tools/generate_poc.py +1329 -0
  251. package/skills/zeroize-audit/tools/mcp/apply_confidence_gates.py +113 -0
  252. package/skills/zeroize-audit/tools/mcp/check_mcp.sh +68 -0
  253. package/skills/zeroize-audit/tools/mcp/normalize_mcp_evidence.py +125 -0
  254. package/skills/zeroize-audit/tools/scripts/check_llvm_patterns.py +481 -0
  255. package/skills/zeroize-audit/tools/scripts/check_mir_patterns.py +554 -0
  256. package/skills/zeroize-audit/tools/scripts/check_rust_asm.py +424 -0
  257. package/skills/zeroize-audit/tools/scripts/check_rust_asm_aarch64.py +300 -0
  258. package/skills/zeroize-audit/tools/scripts/check_rust_asm_x86.py +283 -0
  259. package/skills/zeroize-audit/tools/scripts/find_dangerous_apis.py +375 -0
  260. package/skills/zeroize-audit/tools/scripts/semantic_audit.py +923 -0
  261. package/skills/zeroize-audit/tools/track_dataflow.sh +196 -0
  262. package/skills/zeroize-audit/tools/validate_rust_toolchain.sh +298 -0
  263. package/skills/zeroize-audit/workflows/phase-0-preflight.md +150 -0
  264. package/skills/zeroize-audit/workflows/phase-1-source-analysis.md +144 -0
  265. package/skills/zeroize-audit/workflows/phase-2-compiler-analysis.md +139 -0
  266. package/skills/zeroize-audit/workflows/phase-3-interim-report.md +46 -0
  267. package/skills/zeroize-audit/workflows/phase-4-poc-generation.md +46 -0
  268. package/skills/zeroize-audit/workflows/phase-5-poc-validation.md +136 -0
  269. package/skills/zeroize-audit/workflows/phase-6-final-report.md +44 -0
  270. package/skills/zeroize-audit/workflows/phase-7-test-generation.md +42 -0
  271. package/themes/piolium-srcery.json +94 -0
@@ -0,0 +1,483 @@
1
+ ---
2
+ name: sarif-parsing
3
+ description: >-
4
+ Parses and processes SARIF files from static analysis tools like CodeQL, Semgrep, or other
5
+ scanners. Triggers on "parse sarif", "read scan results", "aggregate findings", "deduplicate
6
+ alerts", or "process sarif output". Handles filtering, deduplication, format conversion, and
7
+ CI/CD integration of SARIF data. Does NOT run scans — use the Semgrep or CodeQL skills for that.
8
+ allowed-tools:
9
+ - Bash
10
+ - Read
11
+ - Glob
12
+ - Grep
13
+ ---
14
+
15
+ # SARIF Parsing Best Practices
16
+
17
+ You are a SARIF parsing expert. Your role is to help users effectively read, analyze, and process SARIF files from static analysis tools.
18
+
19
+ ## When to Use
20
+
21
+ Use this skill when:
22
+ - Reading or interpreting static analysis scan results in SARIF format
23
+ - Aggregating findings from multiple security tools
24
+ - Deduplicating or filtering security alerts
25
+ - Extracting specific vulnerabilities from SARIF files
26
+ - Integrating SARIF data into CI/CD pipelines
27
+ - Converting SARIF output to other formats
28
+
29
+ ## When NOT to Use
30
+
31
+ Do NOT use this skill for:
32
+ - Running static analysis scans (use CodeQL or Semgrep skills instead)
33
+ - Writing CodeQL or Semgrep rules (use their respective skills)
34
+ - Analyzing source code directly (SARIF is for processing existing scan results)
35
+ - Triaging findings without SARIF input (use variant-analysis or audit skills)
36
+
37
+ ## SARIF Structure Overview
38
+
39
+ SARIF 2.1.0 is the current OASIS standard. Every SARIF file has this hierarchical structure:
40
+
41
+ ```
42
+ sarifLog
43
+ ├── version: "2.1.0"
44
+ ├── $schema: (optional, enables IDE validation)
45
+ └── runs[] (array of analysis runs)
46
+ ├── tool
47
+ │ ├── driver
48
+ │ │ ├── name (required)
49
+ │ │ ├── version
50
+ │ │ └── rules[] (rule definitions)
51
+ │ └── extensions[] (plugins)
52
+ ├── results[] (findings)
53
+ │ ├── ruleId
54
+ │ ├── level (error/warning/note)
55
+ │ ├── message.text
56
+ │ ├── locations[]
57
+ │ │ └── physicalLocation
58
+ │ │ ├── artifactLocation.uri
59
+ │ │ └── region (startLine, startColumn, etc.)
60
+ │ ├── fingerprints{}
61
+ │ └── partialFingerprints{}
62
+ └── artifacts[] (scanned files metadata)
63
+ ```
64
+
65
+ ### Why Fingerprinting Matters
66
+
67
+ Without stable fingerprints, you can't track findings across runs:
68
+
69
+ - **Baseline comparison**: "Is this a new finding or did we see it before?"
70
+ - **Regression detection**: "Did this PR introduce new vulnerabilities?"
71
+ - **Suppression**: "Ignore this known false positive in future runs"
72
+
73
+ Tools report different paths (`/path/to/project/` vs `/github/workspace/`), so path-based matching fails. Fingerprints hash the *content* (code snippet, rule ID, relative location) to create stable identifiers regardless of environment.
74
+
75
+ ## Tool Selection Guide
76
+
77
+ | Use Case | Tool | Installation |
78
+ |----------|------|--------------|
79
+ | Quick CLI queries | jq | `brew install jq` / `apt install jq` |
80
+ | Python scripting (simple) | pysarif | `pip install pysarif` |
81
+ | Python scripting (advanced) | sarif-tools | `pip install sarif-tools` |
82
+ | .NET applications | SARIF SDK | NuGet package |
83
+ | JavaScript/Node.js | sarif-js | npm package |
84
+ | Go applications | garif | `go get github.com/chavacava/garif` |
85
+ | Validation | SARIF Validator | sarifweb.azurewebsites.net |
86
+
87
+ ## Strategy 1: Quick Analysis with jq
88
+
89
+ For rapid exploration and one-off queries:
90
+
91
+ ```bash
92
+ # Pretty print the file
93
+ jq '.' results.sarif
94
+
95
+ # Count total findings
96
+ jq '[.runs[].results[]] | length' results.sarif
97
+
98
+ # List all rule IDs triggered
99
+ jq '[.runs[].results[].ruleId] | unique' results.sarif
100
+
101
+ # Extract errors only
102
+ jq '.runs[].results[] | select(.level == "error")' results.sarif
103
+
104
+ # Get findings with file locations
105
+ jq '.runs[].results[] | {
106
+ rule: .ruleId,
107
+ message: .message.text,
108
+ file: .locations[0].physicalLocation.artifactLocation.uri,
109
+ line: .locations[0].physicalLocation.region.startLine
110
+ }' results.sarif
111
+
112
+ # Filter by severity and get count per rule
113
+ jq '[.runs[].results[] | select(.level == "error")] | group_by(.ruleId) | map({rule: .[0].ruleId, count: length})' results.sarif
114
+
115
+ # Extract findings for a specific file
116
+ jq --arg file "src/auth.py" '.runs[].results[] | select(.locations[].physicalLocation.artifactLocation.uri | contains($file))' results.sarif
117
+ ```
118
+
119
+ ## Strategy 2: Python with pysarif
120
+
121
+ For programmatic access with full object model:
122
+
123
+ ```python
124
+ from pysarif import load_from_file, save_to_file
125
+
126
+ # Load SARIF file
127
+ sarif = load_from_file("results.sarif")
128
+
129
+ # Iterate through runs and results
130
+ for run in sarif.runs:
131
+ tool_name = run.tool.driver.name
132
+ print(f"Tool: {tool_name}")
133
+
134
+ for result in run.results:
135
+ print(f" [{result.level}] {result.rule_id}: {result.message.text}")
136
+
137
+ if result.locations:
138
+ loc = result.locations[0].physical_location
139
+ if loc and loc.artifact_location:
140
+ print(f" File: {loc.artifact_location.uri}")
141
+ if loc.region:
142
+ print(f" Line: {loc.region.start_line}")
143
+
144
+ # Save modified SARIF
145
+ save_to_file(sarif, "modified.sarif")
146
+ ```
147
+
148
+ ## Strategy 3: Python with sarif-tools
149
+
150
+ For aggregation, reporting, and CI/CD integration:
151
+
152
+ ```python
153
+ from sarif import loader
154
+
155
+ # Load single file
156
+ sarif_data = loader.load_sarif_file("results.sarif")
157
+
158
+ # Or load multiple files
159
+ sarif_set = loader.load_sarif_files(["tool1.sarif", "tool2.sarif"])
160
+
161
+ # Get summary report
162
+ report = sarif_data.get_report()
163
+
164
+ # Get histogram by severity
165
+ errors = report.get_issue_type_histogram_for_severity("error")
166
+ warnings = report.get_issue_type_histogram_for_severity("warning")
167
+
168
+ # Filter results
169
+ high_severity = [r for r in sarif_data.get_results()
170
+ if r.get("level") == "error"]
171
+ ```
172
+
173
+ **sarif-tools CLI commands:**
174
+
175
+ ```bash
176
+ # Summary of findings
177
+ sarif summary results.sarif
178
+
179
+ # List all results with details
180
+ sarif ls results.sarif
181
+
182
+ # Get results by severity
183
+ sarif ls --level error results.sarif
184
+
185
+ # Diff two SARIF files (find new/fixed issues)
186
+ sarif diff baseline.sarif current.sarif
187
+
188
+ # Convert to other formats
189
+ sarif csv results.sarif > results.csv
190
+ sarif html results.sarif > report.html
191
+ ```
192
+
193
+ ## Strategy 4: Aggregating Multiple SARIF Files
194
+
195
+ When combining results from multiple tools:
196
+
197
+ ```python
198
+ import json
199
+ from pathlib import Path
200
+
201
+ def aggregate_sarif_files(sarif_paths: list[str]) -> dict:
202
+ """Combine multiple SARIF files into one."""
203
+ aggregated = {
204
+ "version": "2.1.0",
205
+ "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
206
+ "runs": []
207
+ }
208
+
209
+ for path in sarif_paths:
210
+ with open(path) as f:
211
+ sarif = json.load(f)
212
+ aggregated["runs"].extend(sarif.get("runs", []))
213
+
214
+ return aggregated
215
+
216
+ def deduplicate_results(sarif: dict) -> dict:
217
+ """Remove duplicate findings based on fingerprints."""
218
+ seen_fingerprints = set()
219
+
220
+ for run in sarif["runs"]:
221
+ unique_results = []
222
+ for result in run.get("results", []):
223
+ # Use partialFingerprints or create key from location
224
+ fp = None
225
+ if result.get("partialFingerprints"):
226
+ fp = tuple(sorted(result["partialFingerprints"].items()))
227
+ elif result.get("fingerprints"):
228
+ fp = tuple(sorted(result["fingerprints"].items()))
229
+ else:
230
+ # Fallback: create fingerprint from rule + location
231
+ loc = result.get("locations", [{}])[0]
232
+ phys = loc.get("physicalLocation", {})
233
+ fp = (
234
+ result.get("ruleId"),
235
+ phys.get("artifactLocation", {}).get("uri"),
236
+ phys.get("region", {}).get("startLine")
237
+ )
238
+
239
+ if fp not in seen_fingerprints:
240
+ seen_fingerprints.add(fp)
241
+ unique_results.append(result)
242
+
243
+ run["results"] = unique_results
244
+
245
+ return sarif
246
+ ```
247
+
248
+ ## Strategy 5: Extracting Actionable Data
249
+
250
+ ```python
251
+ import json
252
+ from dataclasses import dataclass
253
+ from typing import Optional
254
+
255
+ @dataclass
256
+ class Finding:
257
+ rule_id: str
258
+ level: str
259
+ message: str
260
+ file_path: Optional[str]
261
+ start_line: Optional[int]
262
+ end_line: Optional[int]
263
+ fingerprint: Optional[str]
264
+
265
+ def extract_findings(sarif_path: str) -> list[Finding]:
266
+ """Extract structured findings from SARIF file."""
267
+ with open(sarif_path) as f:
268
+ sarif = json.load(f)
269
+
270
+ findings = []
271
+ for run in sarif.get("runs", []):
272
+ for result in run.get("results", []):
273
+ loc = result.get("locations", [{}])[0]
274
+ phys = loc.get("physicalLocation", {})
275
+ region = phys.get("region", {})
276
+
277
+ findings.append(Finding(
278
+ rule_id=result.get("ruleId", "unknown"),
279
+ level=result.get("level", "warning"),
280
+ message=result.get("message", {}).get("text", ""),
281
+ file_path=phys.get("artifactLocation", {}).get("uri"),
282
+ start_line=region.get("startLine"),
283
+ end_line=region.get("endLine"),
284
+ fingerprint=next(iter(result.get("partialFingerprints", {}).values()), None)
285
+ ))
286
+
287
+ return findings
288
+
289
+ # Filter and prioritize
290
+ def prioritize_findings(findings: list[Finding]) -> list[Finding]:
291
+ """Sort findings by severity."""
292
+ severity_order = {"error": 0, "warning": 1, "note": 2, "none": 3}
293
+ return sorted(findings, key=lambda f: severity_order.get(f.level, 99))
294
+ ```
295
+
296
+ ## Common Pitfalls and Solutions
297
+
298
+ ### 1. Path Normalization Issues
299
+
300
+ Different tools report paths differently (absolute, relative, URI-encoded):
301
+
302
+ ```python
303
+ from urllib.parse import unquote
304
+ from pathlib import Path
305
+
306
+ def normalize_path(uri: str, base_path: str = "") -> str:
307
+ """Normalize SARIF artifact URI to consistent path."""
308
+ # Remove file:// prefix if present
309
+ if uri.startswith("file://"):
310
+ uri = uri[7:]
311
+
312
+ # URL decode
313
+ uri = unquote(uri)
314
+
315
+ # Handle relative paths
316
+ if not Path(uri).is_absolute() and base_path:
317
+ uri = str(Path(base_path) / uri)
318
+
319
+ # Normalize separators
320
+ return str(Path(uri))
321
+ ```
322
+
323
+ ### 2. Fingerprint Mismatch Across Runs
324
+
325
+ Fingerprints may not match if:
326
+ - File paths differ between environments
327
+ - Tool versions changed fingerprinting algorithm
328
+ - Code was reformatted (changing line numbers)
329
+
330
+ **Solution:** Use multiple fingerprint strategies:
331
+
332
+ ```python
333
+ def compute_stable_fingerprint(result: dict, file_content: str = None) -> str:
334
+ """Compute environment-independent fingerprint."""
335
+ import hashlib
336
+
337
+ components = [
338
+ result.get("ruleId", ""),
339
+ result.get("message", {}).get("text", "")[:100], # First 100 chars
340
+ ]
341
+
342
+ # Add code snippet if available
343
+ if file_content and result.get("locations"):
344
+ region = result["locations"][0].get("physicalLocation", {}).get("region", {})
345
+ if region.get("startLine"):
346
+ lines = file_content.split("\n")
347
+ line_idx = region["startLine"] - 1
348
+ if 0 <= line_idx < len(lines):
349
+ # Normalize whitespace
350
+ components.append(lines[line_idx].strip())
351
+
352
+ return hashlib.sha256("".join(components).encode()).hexdigest()[:16]
353
+ ```
354
+
355
+ ### 3. Missing or Incomplete Data
356
+
357
+ SARIF allows many optional fields. Always use defensive access:
358
+
359
+ ```python
360
+ def safe_get_location(result: dict) -> tuple[str, int]:
361
+ """Safely extract file and line from result."""
362
+ try:
363
+ loc = result.get("locations", [{}])[0]
364
+ phys = loc.get("physicalLocation", {})
365
+ file_path = phys.get("artifactLocation", {}).get("uri", "unknown")
366
+ line = phys.get("region", {}).get("startLine", 0)
367
+ return file_path, line
368
+ except (IndexError, KeyError, TypeError):
369
+ return "unknown", 0
370
+ ```
371
+
372
+ ### 4. Large File Performance
373
+
374
+ For very large SARIF files (100MB+):
375
+
376
+ ```python
377
+ import ijson # pip install ijson
378
+
379
+ def stream_results(sarif_path: str):
380
+ """Stream results without loading entire file."""
381
+ with open(sarif_path, "rb") as f:
382
+ # Stream through results arrays
383
+ for result in ijson.items(f, "runs.item.results.item"):
384
+ yield result
385
+ ```
386
+
387
+ ### 5. Schema Validation
388
+
389
+ Validate before processing to catch malformed files:
390
+
391
+ ```bash
392
+ # Using ajv-cli
393
+ npm install -g ajv-cli
394
+ ajv validate -s sarif-schema-2.1.0.json -d results.sarif
395
+
396
+ # Using Python jsonschema
397
+ pip install jsonschema
398
+ ```
399
+
400
+ ```python
401
+ from jsonschema import validate, ValidationError
402
+ import json
403
+
404
+ def validate_sarif(sarif_path: str, schema_path: str) -> bool:
405
+ """Validate SARIF file against schema."""
406
+ with open(sarif_path) as f:
407
+ sarif = json.load(f)
408
+ with open(schema_path) as f:
409
+ schema = json.load(f)
410
+
411
+ try:
412
+ validate(sarif, schema)
413
+ return True
414
+ except ValidationError as e:
415
+ print(f"Validation error: {e.message}")
416
+ return False
417
+ ```
418
+
419
+ ## CI/CD Integration Patterns
420
+
421
+ ### GitHub Actions
422
+
423
+ ```yaml
424
+ - name: Upload SARIF
425
+ uses: github/codeql-action/upload-sarif@v3
426
+ with:
427
+ sarif_file: results.sarif
428
+
429
+ - name: Check for high severity
430
+ run: |
431
+ HIGH_COUNT=$(jq '[.runs[].results[] | select(.level == "error")] | length' results.sarif)
432
+ if [ "$HIGH_COUNT" -gt 0 ]; then
433
+ echo "Found $HIGH_COUNT high severity issues"
434
+ exit 1
435
+ fi
436
+ ```
437
+
438
+ ### Fail on New Issues
439
+
440
+ ```python
441
+ from sarif import loader
442
+
443
+ def check_for_regressions(baseline: str, current: str) -> int:
444
+ """Return count of new issues not in baseline."""
445
+ baseline_data = loader.load_sarif_file(baseline)
446
+ current_data = loader.load_sarif_file(current)
447
+
448
+ baseline_fps = {get_fingerprint(r) for r in baseline_data.get_results()}
449
+ new_issues = [r for r in current_data.get_results()
450
+ if get_fingerprint(r) not in baseline_fps]
451
+
452
+ return len(new_issues)
453
+ ```
454
+
455
+ ## Key Principles
456
+
457
+ 1. **Validate first**: Check SARIF structure before processing
458
+ 2. **Handle optionals**: Many fields are optional; use defensive access
459
+ 3. **Normalize paths**: Tools report paths differently; normalize early
460
+ 4. **Fingerprint wisely**: Combine multiple strategies for stable deduplication
461
+ 5. **Stream large files**: Use ijson or similar for 100MB+ files
462
+ 6. **Aggregate thoughtfully**: Preserve tool metadata when combining files
463
+
464
+ ## Skill Resources
465
+
466
+ For ready-to-use query templates, see [{baseDir}/resources/jq-queries.md]({baseDir}/resources/jq-queries.md):
467
+ - 40+ jq queries for common SARIF operations
468
+ - Severity filtering, rule extraction, aggregation patterns
469
+
470
+ For Python utilities, see [{baseDir}/resources/sarif_helpers.py]({baseDir}/resources/sarif_helpers.py):
471
+ - `normalize_path()` - Handle tool-specific path formats
472
+ - `compute_fingerprint()` - Stable fingerprinting ignoring paths
473
+ - `deduplicate_results()` - Remove duplicates across runs
474
+
475
+ ## Reference Links
476
+
477
+ - [OASIS SARIF 2.1.0 Specification](https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html)
478
+ - [Microsoft SARIF Tutorials](https://github.com/microsoft/sarif-tutorials)
479
+ - [SARIF SDK (.NET)](https://github.com/microsoft/sarif-sdk)
480
+ - [sarif-tools (Python)](https://github.com/microsoft/sarif-tools)
481
+ - [pysarif (Python)](https://github.com/Kjeld-P/pysarif)
482
+ - [GitHub SARIF Support](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning)
483
+ - [SARIF Validator](https://sarifweb.azurewebsites.net/)
@@ -0,0 +1,162 @@
1
+ # SARIF jq Query Reference
2
+
3
+ Ready-to-use jq queries for common SARIF parsing tasks.
4
+
5
+ ## Basic Exploration
6
+
7
+ ```bash
8
+ # Pretty print
9
+ jq '.' results.sarif
10
+
11
+ # Get SARIF version
12
+ jq '.version' results.sarif
13
+
14
+ # List tool names from all runs
15
+ jq '.runs[].tool.driver.name' results.sarif
16
+
17
+ # Count runs
18
+ jq '.runs | length' results.sarif
19
+ ```
20
+
21
+ ## Result Queries
22
+
23
+ ```bash
24
+ # Total result count
25
+ jq '[.runs[].results[]] | length' results.sarif
26
+
27
+ # Count by severity level
28
+ jq 'reduce .runs[].results[] as $r ({}; .[$r.level] += 1)' results.sarif
29
+
30
+ # List unique rule IDs
31
+ jq '[.runs[].results[].ruleId] | unique | sort' results.sarif
32
+
33
+ # Count per rule
34
+ jq '[.runs[].results[]] | group_by(.ruleId) | map({rule: .[0].ruleId, count: length}) | sort_by(-.count)' results.sarif
35
+ ```
36
+
37
+ ## Filtering Results
38
+
39
+ ```bash
40
+ # Only errors
41
+ jq '.runs[].results[] | select(.level == "error")' results.sarif
42
+
43
+ # Only warnings
44
+ jq '.runs[].results[] | select(.level == "warning")' results.sarif
45
+
46
+ # By specific rule ID
47
+ jq --arg rule "SQL_INJECTION" '.runs[].results[] | select(.ruleId == $rule)' results.sarif
48
+
49
+ # By file path (contains)
50
+ jq --arg file "auth" '.runs[].results[] | select(.locations[].physicalLocation.artifactLocation.uri | contains($file))' results.sarif
51
+
52
+ # By file extension
53
+ jq '.runs[].results[] | select(.locations[].physicalLocation.artifactLocation.uri | test("\\.py$"))' results.sarif
54
+
55
+ # Multiple conditions
56
+ jq '.runs[].results[] | select(.level == "error" and (.ruleId | startswith("SEC")))' results.sarif
57
+ ```
58
+
59
+ ## Extracting Locations
60
+
61
+ ```bash
62
+ # File and line for each result
63
+ jq '.runs[].results[] | {
64
+ rule: .ruleId,
65
+ file: .locations[0].physicalLocation.artifactLocation.uri,
66
+ line: .locations[0].physicalLocation.region.startLine
67
+ }' results.sarif
68
+
69
+ # Unique affected files
70
+ jq '[.runs[].results[].locations[].physicalLocation.artifactLocation.uri] | unique | sort' results.sarif
71
+
72
+ # Results grouped by file
73
+ jq '[.runs[].results[] | {file: .locations[0].physicalLocation.artifactLocation.uri, result: .}] | group_by(.file) | map({file: .[0].file, count: length})' results.sarif
74
+ ```
75
+
76
+ ## Rule Information
77
+
78
+ ```bash
79
+ # List all rules with severity
80
+ jq '.runs[].tool.driver.rules[] | {id: .id, name: .name, level: .defaultConfiguration.level}' results.sarif
81
+
82
+ # Get rule description by ID
83
+ jq --arg id "RULE001" '.runs[].tool.driver.rules[] | select(.id == $id)' results.sarif
84
+
85
+ # Rules with help URLs
86
+ jq '.runs[].tool.driver.rules[] | select(.helpUri) | {id: .id, help: .helpUri}' results.sarif
87
+ ```
88
+
89
+ ## Fingerprints
90
+
91
+ ```bash
92
+ # Results with fingerprints
93
+ jq '.runs[].results[] | select(.fingerprints or .partialFingerprints) | {rule: .ruleId, fp: (.fingerprints // .partialFingerprints)}' results.sarif
94
+
95
+ # Extract all partial fingerprints
96
+ jq '[.runs[].results[].partialFingerprints] | add' results.sarif
97
+ ```
98
+
99
+ ## Aggregation and Reporting
100
+
101
+ ```bash
102
+ # Summary by severity and rule
103
+ jq '[.runs[].results[]] | group_by(.level) | map({level: .[0].level, rules: (group_by(.ruleId) | map({rule: .[0].ruleId, count: length}))})' results.sarif
104
+
105
+ # Top 10 most frequent rules
106
+ jq '[.runs[].results[]] | group_by(.ruleId) | map({rule: .[0].ruleId, count: length}) | sort_by(-.count) | .[0:10]' results.sarif
107
+
108
+ # Files with most issues
109
+ jq '[.runs[].results[] | .locations[0].physicalLocation.artifactLocation.uri] | group_by(.) | map({file: .[0], count: length}) | sort_by(-.count) | .[0:10]' results.sarif
110
+ ```
111
+
112
+ ## Output Formatting
113
+
114
+ ```bash
115
+ # CSV-like output
116
+ jq -r '.runs[].results[] | [.ruleId, .level, .locations[0].physicalLocation.artifactLocation.uri, .locations[0].physicalLocation.region.startLine, .message.text] | @csv' results.sarif
117
+
118
+ # Tab-separated
119
+ jq -r '.runs[].results[] | [.ruleId, .level, .locations[0].physicalLocation.artifactLocation.uri // "N/A"] | @tsv' results.sarif
120
+
121
+ # Markdown table
122
+ echo "| Rule | Level | File | Line |"
123
+ echo "|------|-------|------|------|"
124
+ jq -r '.runs[].results[] | "| \(.ruleId) | \(.level) | \(.locations[0].physicalLocation.artifactLocation.uri // "N/A") | \(.locations[0].physicalLocation.region.startLine // "N/A") |"' results.sarif
125
+ ```
126
+
127
+ ## Comparison and Diff
128
+
129
+ ```bash
130
+ # Find rules in file1 not in file2
131
+ comm -23 <(jq -r '[.runs[].results[].ruleId] | unique | sort[]' file1.sarif) <(jq -r '[.runs[].results[].ruleId] | unique | sort[]' file2.sarif)
132
+
133
+ # Compare result counts
134
+ echo "File 1: $(jq '[.runs[].results[]] | length' file1.sarif)"
135
+ echo "File 2: $(jq '[.runs[].results[]] | length' file2.sarif)"
136
+ ```
137
+
138
+ ## Transformation
139
+
140
+ ```bash
141
+ # Extract minimal SARIF (results only)
142
+ jq '{version: .version, runs: [.runs[] | {tool: {driver: {name: .tool.driver.name}}, results: .results}]}' results.sarif
143
+
144
+ # Filter and create new SARIF with only errors
145
+ jq '.runs[].results = [.runs[].results[] | select(.level == "error")]' results.sarif > errors-only.sarif
146
+
147
+ # Merge multiple SARIF files
148
+ jq -s '{version: "2.1.0", runs: [.[].runs[]]}' file1.sarif file2.sarif > merged.sarif
149
+ ```
150
+
151
+ ## Validation Checks
152
+
153
+ ```bash
154
+ # Check if version is 2.1.0
155
+ jq -e '.version == "2.1.0"' results.sarif && echo "Valid version" || echo "Invalid version"
156
+
157
+ # Check for empty results
158
+ jq -e '[.runs[].results[]] | length > 0' results.sarif && echo "Has results" || echo "No results"
159
+
160
+ # Verify all results have locations
161
+ jq '[.runs[].results[] | select(.locations | length == 0)] | length' results.sarif
162
+ ```