zizmor 1.2.0__tar.gz → 1.2.1__tar.gz

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.

Potentially problematic release.


This version of zizmor might be problematic. Click here for more details.

Files changed (192) hide show
  1. {zizmor-1.2.0 → zizmor-1.2.1}/.github/workflows/ci.yml +14 -2
  2. {zizmor-1.2.0 → zizmor-1.2.1}/.github/workflows/site.yml +1 -1
  3. {zizmor-1.2.0 → zizmor-1.2.1}/.github/workflows/zizmor.yml +1 -1
  4. {zizmor-1.2.0 → zizmor-1.2.1}/Cargo.lock +1 -1
  5. {zizmor-1.2.0 → zizmor-1.2.1}/Cargo.toml +1 -1
  6. {zizmor-1.2.0 → zizmor-1.2.1}/Makefile +4 -4
  7. {zizmor-1.2.0 → zizmor-1.2.1}/PKG-INFO +3 -1
  8. {zizmor-1.2.0 → zizmor-1.2.1}/docs/release-notes.md +10 -0
  9. {zizmor-1.2.0 → zizmor-1.2.1}/docs/usage.md +1 -1
  10. zizmor-1.2.1/pyproject.toml +17 -0
  11. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/bot_conditions.rs +2 -3
  12. {zizmor-1.2.0 → zizmor-1.2.1}/src/main.rs +17 -13
  13. {zizmor-1.2.0 → zizmor-1.2.1}/src/models.rs +8 -13
  14. {zizmor-1.2.0 → zizmor-1.2.1}/src/registry.rs +53 -18
  15. {zizmor-1.2.0 → zizmor-1.2.1}/src/render.rs +5 -1
  16. {zizmor-1.2.0 → zizmor-1.2.1}/src/sarif.rs +2 -1
  17. zizmor-1.2.1/uv.lock +869 -0
  18. zizmor-1.2.0/pyproject.toml +0 -6
  19. zizmor-1.2.0/site-requirements.txt +0 -2
  20. {zizmor-1.2.0 → zizmor-1.2.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  21. {zizmor-1.2.0 → zizmor-1.2.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  22. {zizmor-1.2.0 → zizmor-1.2.1}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  23. {zizmor-1.2.0 → zizmor-1.2.1}/.github/dependabot.yml +0 -0
  24. {zizmor-1.2.0 → zizmor-1.2.1}/.github/workflows/pypi.yml +0 -0
  25. {zizmor-1.2.0 → zizmor-1.2.1}/.github/workflows/release.yml +0 -0
  26. {zizmor-1.2.0 → zizmor-1.2.1}/.gitignore +0 -0
  27. {zizmor-1.2.0 → zizmor-1.2.1}/CONTRIBUTING.md +0 -0
  28. {zizmor-1.2.0 → zizmor-1.2.1}/LICENSE +0 -0
  29. {zizmor-1.2.0 → zizmor-1.2.1}/README.md +0 -0
  30. {zizmor-1.2.0 → zizmor-1.2.1}/docs/assets/favicon48x48.png +0 -0
  31. {zizmor-1.2.0 → zizmor-1.2.1}/docs/assets/rainbow.svg +0 -0
  32. {zizmor-1.2.0 → zizmor-1.2.1}/docs/assets/zizmor-demo.gif +0 -0
  33. {zizmor-1.2.0 → zizmor-1.2.1}/docs/audits.md +0 -0
  34. {zizmor-1.2.0 → zizmor-1.2.1}/docs/configuration.md +0 -0
  35. {zizmor-1.2.0 → zizmor-1.2.1}/docs/development.md +0 -0
  36. {zizmor-1.2.0 → zizmor-1.2.1}/docs/index.md +0 -0
  37. {zizmor-1.2.0 → zizmor-1.2.1}/docs/installation.md +0 -0
  38. {zizmor-1.2.0 → zizmor-1.2.1}/docs/magiclink.css +0 -0
  39. {zizmor-1.2.0 → zizmor-1.2.1}/docs/quickstart.md +0 -0
  40. {zizmor-1.2.0 → zizmor-1.2.1}/docs/snippets/help.txt +0 -0
  41. {zizmor-1.2.0 → zizmor-1.2.1}/docs/snippets/render-sponsors.py +0 -0
  42. {zizmor-1.2.0 → zizmor-1.2.1}/docs/snippets/render-trophies.py +0 -0
  43. {zizmor-1.2.0 → zizmor-1.2.1}/docs/snippets/sponsors.html +0 -0
  44. {zizmor-1.2.0 → zizmor-1.2.1}/docs/snippets/sponsors.json +0 -0
  45. {zizmor-1.2.0 → zizmor-1.2.1}/docs/snippets/trophies.md +0 -0
  46. {zizmor-1.2.0 → zizmor-1.2.1}/docs/snippets/trophies.txt +0 -0
  47. {zizmor-1.2.0 → zizmor-1.2.1}/docs/trophy-case.md +0 -0
  48. {zizmor-1.2.0 → zizmor-1.2.1}/mkdocs.yml +0 -0
  49. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/artipacked.rs +0 -0
  50. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/cache_poisoning.rs +0 -0
  51. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/dangerous_triggers.rs +0 -0
  52. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/excessive_permissions.rs +0 -0
  53. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/github_env.rs +0 -0
  54. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/hardcoded_container_credentials.rs +0 -0
  55. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/impostor_commit.rs +0 -0
  56. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/insecure_commands.rs +0 -0
  57. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/known_vulnerable_actions.rs +0 -0
  58. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/mod.rs +0 -0
  59. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/ref_confusion.rs +0 -0
  60. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/secrets_inherit.rs +0 -0
  61. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/self_hosted_runner.rs +0 -0
  62. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/template_injection.rs +0 -0
  63. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/unpinned_uses.rs +0 -0
  64. {zizmor-1.2.0 → zizmor-1.2.1}/src/audit/use_trusted_publishing.rs +0 -0
  65. {zizmor-1.2.0 → zizmor-1.2.1}/src/config.rs +0 -0
  66. {zizmor-1.2.0 → zizmor-1.2.1}/src/expr/expr.pest +0 -0
  67. {zizmor-1.2.0 → zizmor-1.2.1}/src/expr/mod.rs +0 -0
  68. {zizmor-1.2.0 → zizmor-1.2.1}/src/finding/locate.rs +0 -0
  69. {zizmor-1.2.0 → zizmor-1.2.1}/src/finding/mod.rs +0 -0
  70. {zizmor-1.2.0 → zizmor-1.2.1}/src/github_api.rs +0 -0
  71. {zizmor-1.2.0 → zizmor-1.2.1}/src/models/coordinate.rs +0 -0
  72. {zizmor-1.2.0 → zizmor-1.2.1}/src/models/uses.rs +0 -0
  73. {zizmor-1.2.0 → zizmor-1.2.1}/src/state.rs +0 -0
  74. {zizmor-1.2.0 → zizmor-1.2.1}/src/utils.rs +0 -0
  75. {zizmor-1.2.0 → zizmor-1.2.1}/tests/acceptance.rs +0 -0
  76. {zizmor-1.2.0 → zizmor-1.2.1}/tests/common.rs +0 -0
  77. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshot.rs +0 -0
  78. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__artipacked-2.snap +0 -0
  79. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__artipacked-3.snap +0 -0
  80. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__artipacked-4.snap +0 -0
  81. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__artipacked.snap +0 -0
  82. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__bot_conditions.snap +0 -0
  83. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-10.snap +0 -0
  84. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-11.snap +0 -0
  85. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-12.snap +0 -0
  86. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-13.snap +0 -0
  87. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-14.snap +0 -0
  88. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-2.snap +0 -0
  89. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-3.snap +0 -0
  90. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-4.snap +0 -0
  91. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-5.snap +0 -0
  92. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-6.snap +0 -0
  93. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-7.snap +0 -0
  94. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-8.snap +0 -0
  95. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning-9.snap +0 -0
  96. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cache_poisoning.snap +0 -0
  97. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__cant_retrieve.snap +0 -0
  98. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__conflicting_online_options-2.snap +0 -0
  99. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__conflicting_online_options-3.snap +0 -0
  100. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__conflicting_online_options.snap +0 -0
  101. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__excessive_permissions-2.snap +0 -0
  102. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__excessive_permissions-3.snap +0 -0
  103. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__excessive_permissions-4.snap +0 -0
  104. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__excessive_permissions-5.snap +0 -0
  105. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__excessive_permissions-6.snap +0 -0
  106. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__excessive_permissions-7.snap +0 -0
  107. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__excessive_permissions-8.snap +0 -0
  108. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__excessive_permissions-9.snap +0 -0
  109. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__excessive_permissions.snap +0 -0
  110. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__github_env-2.snap +0 -0
  111. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__github_env-3.snap +0 -0
  112. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__github_env.snap +0 -0
  113. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__insecure_commands-2.snap +0 -0
  114. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__insecure_commands-3.snap +0 -0
  115. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__insecure_commands.snap +0 -0
  116. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__secrets_inherit.snap +0 -0
  117. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__self_hosted-2.snap +0 -0
  118. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__self_hosted-3.snap +0 -0
  119. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__self_hosted-4.snap +0 -0
  120. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__self_hosted-5.snap +0 -0
  121. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__self_hosted-6.snap +0 -0
  122. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__self_hosted-7.snap +0 -0
  123. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__self_hosted-8.snap +0 -0
  124. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__self_hosted.snap +0 -0
  125. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__template_injection-2.snap +0 -0
  126. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__template_injection-3.snap +0 -0
  127. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__template_injection-4.snap +0 -0
  128. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__template_injection-5.snap +0 -0
  129. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__template_injection-6.snap +0 -0
  130. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__template_injection-7.snap +0 -0
  131. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__template_injection-8.snap +0 -0
  132. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__template_injection.snap +0 -0
  133. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__unpinned_uses-2.snap +0 -0
  134. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__unpinned_uses-3.snap +0 -0
  135. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__unpinned_uses-4.snap +0 -0
  136. {zizmor-1.2.0 → zizmor-1.2.1}/tests/snapshots/snapshot__unpinned_uses.snap +0 -0
  137. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/artipacked/issue-447-repro.yml +0 -0
  138. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/artipacked.yml +0 -0
  139. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/bot-conditions.yml +0 -0
  140. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/caching-disabled-by-default.yml +0 -0
  141. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/caching-enabled-by-default.yml +0 -0
  142. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/caching-not-configurable.yml +0 -0
  143. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/caching-opt-in-boolean-toggle.yml +0 -0
  144. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/caching-opt-in-boolish-toggle.yml +0 -0
  145. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/caching-opt-in-expression.yml +0 -0
  146. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/caching-opt-in-multi-value-toggle.yml +0 -0
  147. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/caching-opt-out.yml +0 -0
  148. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/issue-343-repro.yml +0 -0
  149. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/issue-378-repro.yml +0 -0
  150. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/no-cache-aware-steps.yml +0 -0
  151. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/publisher-step.yml +0 -0
  152. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/workflow-release-branch-trigger.yml +0 -0
  153. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning/workflow-tag-trigger.yml +0 -0
  154. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/cache-poisoning.yml +0 -0
  155. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/excessive-permissions/issue-336-repro.yml +0 -0
  156. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/excessive-permissions/jobs-broaden-permissions.yml +0 -0
  157. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/excessive-permissions/workflow-default-perms-all-jobs-explicit.yml +0 -0
  158. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/excessive-permissions/workflow-default-perms.yml +0 -0
  159. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/excessive-permissions/workflow-empty-perms.yml +0 -0
  160. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/excessive-permissions/workflow-read-all.yml +0 -0
  161. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/excessive-permissions/workflow-write-all.yml +0 -0
  162. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/excessive-permissions/workflow-write-explicit.yml +0 -0
  163. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/excessive-permissions.yml +0 -0
  164. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/github-env/action.yml +0 -0
  165. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/github-env/github-path.yml +0 -0
  166. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/github-env/issue-397-repro.yml +0 -0
  167. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/github_env.yml +0 -0
  168. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/hardcoded-credentials.yml +0 -0
  169. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/inlined-ignores.yml +0 -0
  170. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/insecure-commands/action.yml +0 -0
  171. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/insecure-commands.yml +0 -0
  172. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/secrets-inherit.yml +0 -0
  173. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/self-hosted/issue-283-repro.yml +0 -0
  174. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/self-hosted/self-hosted-matrix-dimension.yml +0 -0
  175. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/self-hosted/self-hosted-matrix-exclusion.yml +0 -0
  176. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/self-hosted/self-hosted-matrix-inclusion.yml +0 -0
  177. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/self-hosted/self-hosted-runner-group.yml +0 -0
  178. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/self-hosted/self-hosted-runner-label.yml +0 -0
  179. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/self-hosted.yml +0 -0
  180. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/template-injection/issue-22-repro.yml +0 -0
  181. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/template-injection/issue-339-repro.yml +0 -0
  182. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/template-injection/issue-418-repro.yml +0 -0
  183. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/template-injection/pr-317-repro.yml +0 -0
  184. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/template-injection/pr-425-backstop/action.yml +0 -0
  185. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/template-injection/static-env.yml +0 -0
  186. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/template-injection/template-injection-dynamic-matrix.yml +0 -0
  187. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/template-injection/template-injection-static-matrix.yml +0 -0
  188. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/template-injection.yml +0 -0
  189. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/unpinned-uses/action.yml +0 -0
  190. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/unpinned-uses/issue-433-repro.yml +0 -0
  191. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/unpinned-uses.yml +0 -0
  192. {zizmor-1.2.0 → zizmor-1.2.1}/tests/test-data/use-trusted-publishing.yml +0 -0
@@ -33,7 +33,7 @@ jobs:
33
33
 
34
34
  - uses: Swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
35
35
 
36
- - uses: astral-sh/setup-uv@887a942a15af3a7626099df99e897a18d9e5ab3a # v5.1.0
36
+ - uses: astral-sh/setup-uv@b5f58b2abc5763ade55e4e9d0fe52cd1ff7979ca # v5.2.1
37
37
 
38
38
  - name: Test
39
39
  run: cargo test
@@ -43,9 +43,21 @@ jobs:
43
43
  make snippets
44
44
  git diff --exit-code
45
45
 
46
+ test-site:
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
50
+ with:
51
+ persist-credentials: false
52
+
53
+ - uses: astral-sh/setup-uv@b5f58b2abc5763ade55e4e9d0fe52cd1ff7979ca # v5.2.1
54
+
55
+ - name: Test site
56
+ run: make site
57
+
46
58
  all-tests-pass:
47
59
  if: always()
48
- needs: [lint, test]
60
+ needs: [lint, test, test-site]
49
61
  runs-on: ubuntu-latest
50
62
 
51
63
  steps:
@@ -30,7 +30,7 @@ jobs:
30
30
  persist-credentials: false
31
31
 
32
32
  - name: Install the latest version of uv
33
- uses: astral-sh/setup-uv@887a942a15af3a7626099df99e897a18d9e5ab3a # v3
33
+ uses: astral-sh/setup-uv@b5f58b2abc5763ade55e4e9d0fe52cd1ff7979ca # v5.2.1
34
34
 
35
35
  - name: build site
36
36
  run: make site
@@ -19,7 +19,7 @@ jobs:
19
19
  with:
20
20
  persist-credentials: false
21
21
  - name: Install the latest version of uv
22
- uses: astral-sh/setup-uv@887a942a15af3a7626099df99e897a18d9e5ab3a # v4
22
+ uses: astral-sh/setup-uv@b5f58b2abc5763ade55e4e9d0fe52cd1ff7979ca # v5.2.1
23
23
  - name: Run zizmor 🌈
24
24
  run: uvx zizmor --format sarif . > results.sarif
25
25
  env:
@@ -3108,7 +3108,7 @@ dependencies = [
3108
3108
 
3109
3109
  [[package]]
3110
3110
  name = "zizmor"
3111
- version = "1.2.0"
3111
+ version = "1.2.1"
3112
3112
  dependencies = [
3113
3113
  "annotate-snippets",
3114
3114
  "anstream",
@@ -1,7 +1,7 @@
1
1
  [package]
2
2
  name = "zizmor"
3
3
  description = "Static analysis for GitHub Actions"
4
- version = "1.2.0"
4
+ version = "1.2.1"
5
5
  edition = "2021"
6
6
  repository = "https://github.com/woodruffw/zizmor"
7
7
  homepage = "https://github.com/woodruffw/zizmor"
@@ -3,12 +3,12 @@ all:
3
3
  @echo "Run my targets individually!"
4
4
 
5
5
  .PHONY: site
6
- site: site-requirements.txt
7
- uvx --with-requirements $< mkdocs build
6
+ site:
7
+ uv run --only-group docs mkdocs build
8
8
 
9
9
  .PHONY: site-live
10
- site-live: site-requirements.txt
11
- uvx --with-requirements $< mkdocs serve
10
+ site-live:
11
+ uv run --only-group docs mkdocs serve
12
12
 
13
13
  .PHONY: snippets
14
14
  snippets: trophies sponsors
@@ -1,12 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zizmor
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
+ License-File: LICENSE
4
5
  Summary: Static analysis for GitHub Actions
5
6
  Keywords: cli,github-actions,static-analysis,security
6
7
  Home-Page: https://github.com/woodruffw/zizmor
7
8
  Author: William Woodruff <william@yossarian.net>
8
9
  Author-email: William Woodruff <william@yossarian.net>
9
10
  License: MIT
11
+ Requires-Python: >=3.9
10
12
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
11
13
  Project-URL: Source Code, https://github.com/woodruffw/zizmor
12
14
 
@@ -11,6 +11,16 @@ of `zizmor`.
11
11
 
12
12
  Nothing to see here (yet!)
13
13
 
14
+ ## v1.2.1
15
+
16
+ This is a small corrective release for some SARIF behavior that
17
+ changed with v1.2.0.
18
+
19
+ ### Bug Fixes 🐛
20
+
21
+ * SARIF outputs now use relative paths again, but more correctly
22
+ than before [v1.2.0](#v120) (#469)
23
+
14
24
  ## v1.2.0
15
25
 
16
26
  This release comes with one new audit ([bot-conditions]), plus a handful
@@ -457,7 +457,7 @@ To do so, add the following to your `.pre-commit-config.yaml` `repos` section:
457
457
 
458
458
  ```yaml
459
459
  - repo: https://github.com/woodruffw/zizmor-pre-commit
460
- rev: v1.2.0 # (1)!
460
+ rev: v1.2.1 # (1)!
461
461
  hooks:
462
462
  - id: zizmor
463
463
  ```
@@ -0,0 +1,17 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.0,<2.0"]
3
+ build-backend = "maturin"
4
+
5
+ # NOTE: This section is a stub; needed to prevent
6
+ # `uv run --only-group docs` from failing.
7
+ [project]
8
+ name = "zizmor"
9
+ dynamic = ["version"]
10
+ # Arbitrarily set to the oldest non-EOL Python.
11
+ requires-python = ">=3.9"
12
+
13
+ [tool.maturin]
14
+ bindings = "bin"
15
+
16
+ [dependency-groups]
17
+ docs = ["mkdocs ~= 1.6", "mkdocs-material[imaging] ~= 9.5"]
@@ -1,13 +1,12 @@
1
1
  use github_actions_models::common::{expr::ExplicitExpr, If};
2
2
 
3
+ use super::{audit_meta, Audit};
3
4
  use crate::{
4
5
  expr::{self, Expr},
5
6
  finding::{Confidence, Severity},
6
7
  models::JobExt,
7
8
  };
8
9
 
9
- use super::{audit_meta, Audit};
10
-
11
10
  pub(crate) struct BotConditions;
12
11
 
13
12
  audit_meta!(BotConditions, "bot-conditions", "spoofable bot actor check");
@@ -152,7 +151,7 @@ impl BotConditions {
152
151
  // We have a bot condition but it doesn't dominate the expression.
153
152
  (true, false) => Some(Confidence::Medium),
154
153
  // No bot condition.
155
- (_, _) => None,
154
+ (..) => None,
156
155
  }
157
156
  }
158
157
  }
@@ -160,17 +160,18 @@ fn tip(err: impl AsRef<str>, tip: impl AsRef<str>) -> String {
160
160
 
161
161
  #[instrument(skip(mode, registry))]
162
162
  fn collect_from_repo_dir(
163
- repo_dir: &Utf8Path,
163
+ top_dir: &Utf8Path,
164
+ current_dir: &Utf8Path,
164
165
  mode: &CollectionMode,
165
166
  registry: &mut InputRegistry,
166
167
  ) -> Result<()> {
167
168
  // The workflow directory might not exist if we're collecting from
168
169
  // a repository that only contains actions.
169
170
  if mode.workflows() {
170
- let workflow_dir = if repo_dir.ends_with(".github/workflows") {
171
- repo_dir.into()
171
+ let workflow_dir = if current_dir.ends_with(".github/workflows") {
172
+ current_dir.into()
172
173
  } else {
173
- repo_dir.join(".github/workflows")
174
+ current_dir.join(".github/workflows")
174
175
  };
175
176
 
176
177
  if workflow_dir.is_dir() {
@@ -180,7 +181,7 @@ fn collect_from_repo_dir(
180
181
  match input_path.extension() {
181
182
  Some(ext) if ext == "yml" || ext == "yaml" => {
182
183
  registry
183
- .register_by_path(input_path)
184
+ .register_by_path(input_path, Some(top_dir))
184
185
  .with_context(|| format!("failed to register input: {input_path}"))?;
185
186
  }
186
187
  _ => continue,
@@ -192,18 +193,18 @@ fn collect_from_repo_dir(
192
193
  }
193
194
 
194
195
  if mode.actions() {
195
- for entry in repo_dir.read_dir_utf8()? {
196
+ for entry in current_dir.read_dir_utf8()? {
196
197
  let entry = entry?;
197
198
  let entry_path = entry.path();
198
199
 
199
200
  if entry_path.is_file()
200
201
  && matches!(entry_path.file_name(), Some("action.yml" | "action.yaml"))
201
202
  {
202
- let action = Action::from_file(entry_path)?;
203
+ let action = Action::from_file(entry_path, Some(top_dir))?;
203
204
  registry.register_input(action.into())?;
204
205
  } else if entry_path.is_dir() && !entry_path.ends_with(".github/workflows") {
205
206
  // Recurse and limit the collection mode to only actions.
206
- collect_from_repo_dir(entry_path, &CollectionMode::ActionsOnly, registry)?;
207
+ collect_from_repo_dir(top_dir, entry_path, &CollectionMode::ActionsOnly, registry)?;
207
208
  }
208
209
  }
209
210
  }
@@ -285,13 +286,13 @@ fn collect_inputs(
285
286
  for input in inputs {
286
287
  let input_path = Utf8Path::new(input);
287
288
  if input_path.is_file() {
289
+ // When collecting individual files, we don't know which part
290
+ // of the input path is the prefix.
288
291
  registry
289
- .register_by_path(input_path)
292
+ .register_by_path(input_path, None)
290
293
  .with_context(|| format!("failed to register input: {input_path}"))?;
291
294
  } else if input_path.is_dir() {
292
- // TODO: walk directory to discover composite actions.
293
- let absolute = input_path.canonicalize_utf8()?;
294
- collect_from_repo_dir(&absolute, mode, &mut registry)?;
295
+ collect_from_repo_dir(input_path, input_path, mode, &mut registry)?;
295
296
  } else {
296
297
  // If this input isn't a file or directory, it's probably an
297
298
  // `owner/repo(@ref)?` slug.
@@ -387,7 +388,10 @@ fn run() -> Result<ExitCode> {
387
388
  })?);
388
389
  Span::current().pb_inc(1);
389
390
  }
390
- tracing::info!("🌈 completed {input}", input = input.key().path());
391
+ tracing::info!(
392
+ "🌈 completed {input}",
393
+ input = input.key().best_effort_relative_path()
394
+ );
391
395
  }
392
396
  }
393
397
 
@@ -101,7 +101,7 @@ impl Workflow {
101
101
  InputKey::Local(_) => None,
102
102
  InputKey::Remote(_) => {
103
103
  // NOTE: InputKey's Display produces a URL, hence `key.to_string()`.
104
- Some(Link::new(key.path(), &key.to_string()).to_string())
104
+ Some(Link::new(key.best_effort_relative_path(), &key.to_string()).to_string())
105
105
  }
106
106
  };
107
107
 
@@ -114,11 +114,9 @@ impl Workflow {
114
114
  }
115
115
 
116
116
  /// Load a workflow from the given file on disk.
117
- pub(crate) fn from_file<P: AsRef<Utf8Path>>(p: P) -> Result<Self> {
118
- let contents = std::fs::read_to_string(p.as_ref())?;
119
- let path = p.as_ref().canonicalize_utf8()?;
120
-
121
- Self::from_string(contents, InputKey::local(path)?)
117
+ pub(crate) fn from_file<P: AsRef<Utf8Path>>(path: P, prefix: Option<P>) -> Result<Self> {
118
+ let contents = std::fs::read_to_string(path.as_ref())?;
119
+ Self::from_string(contents, InputKey::local(path, prefix)?)
122
120
  }
123
121
 
124
122
  /// This workflow's [`SymbolicLocation`].
@@ -716,13 +714,10 @@ impl Debug for Action {
716
714
 
717
715
  impl Action {
718
716
  /// Load an action from the given file on disk.
719
- pub(crate) fn from_file<P: AsRef<Utf8Path>>(p: P) -> Result<Self> {
717
+ pub(crate) fn from_file<P: AsRef<Utf8Path>>(path: P, prefix: Option<P>) -> Result<Self> {
720
718
  let contents =
721
- std::fs::read_to_string(p.as_ref()).with_context(|| "couldn't read action file")?;
722
-
723
- let path = p.as_ref().canonicalize_utf8()?;
724
-
725
- Self::from_string(contents, InputKey::local(path)?)
719
+ std::fs::read_to_string(path.as_ref()).with_context(|| "couldn't read action file")?;
720
+ Self::from_string(contents, InputKey::local(path, prefix)?)
726
721
  }
727
722
 
728
723
  /// Load a workflow from a buffer, with an assigned name.
@@ -736,7 +731,7 @@ impl Action {
736
731
  InputKey::Local(_) => None,
737
732
  InputKey::Remote(_) => {
738
733
  // NOTE: InputKey's Display produces a URL, hence `key.to_string()`.
739
- Some(Link::new(key.path(), &key.to_string()).to_string())
734
+ Some(Link::new(key.best_effort_relative_path(), &key.to_string()).to_string())
740
735
  }
741
736
  };
742
737
 
@@ -20,7 +20,10 @@ use crate::{
20
20
 
21
21
  #[derive(Debug, Clone, Eq, Hash, PartialEq, Serialize)]
22
22
  pub(crate) struct LocalKey {
23
- path: Utf8PathBuf,
23
+ /// The path's nondeterministic prefix, if any.
24
+ prefix: Option<Utf8PathBuf>,
25
+ /// The given path to the input. This can be absolute or relative.
26
+ given_path: Utf8PathBuf,
24
27
  }
25
28
 
26
29
  #[derive(Debug, Clone, Eq, Hash, PartialEq, Serialize)]
@@ -45,7 +48,7 @@ pub(crate) enum InputKey {
45
48
  impl Display for InputKey {
46
49
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47
50
  match self {
48
- InputKey::Local(local) => write!(f, "file://{path}", path = local.path),
51
+ InputKey::Local(local) => write!(f, "file://{path}", path = local.given_path),
49
52
  InputKey::Remote(remote) => {
50
53
  // No ref means assume HEAD, i.e. whatever's on the default branch.
51
54
  let git_ref = remote.git_ref.as_deref().unwrap_or("HEAD");
@@ -62,13 +65,16 @@ impl Display for InputKey {
62
65
  }
63
66
 
64
67
  impl InputKey {
65
- pub(crate) fn local(path: Utf8PathBuf) -> Result<Self> {
68
+ pub(crate) fn local<P: AsRef<Utf8Path>>(path: P, prefix: Option<P>) -> Result<Self> {
66
69
  // All keys must have a filename component.
67
- if path.file_name().is_none() {
70
+ if path.as_ref().file_name().is_none() {
68
71
  return Err(anyhow!("invalid local input: no filename component"));
69
72
  }
70
73
 
71
- Ok(Self::Local(LocalKey { path }))
74
+ Ok(Self::Local(LocalKey {
75
+ prefix: prefix.map(|p| p.as_ref().to_path_buf()),
76
+ given_path: path.as_ref().to_path_buf(),
77
+ }))
72
78
  }
73
79
 
74
80
  pub(crate) fn remote(slug: &RepositoryUses, path: String) -> Result<Self> {
@@ -84,13 +90,18 @@ impl InputKey {
84
90
  }))
85
91
  }
86
92
 
87
- /// Returns this [`InputKey`]'s filepath component.
93
+ /// Return a "best-effort" relative path for this [`InputKey`].
88
94
  ///
89
- /// This will be an absolute path for local keys, and a relative
90
- /// path for remote keys.
91
- pub(crate) fn path(&self) -> &str {
95
+ /// This will always be a relative path for remote keys,
96
+ /// and will be a "best-effort" relative path for local keys.
97
+ pub(crate) fn best_effort_relative_path(&self) -> &str {
92
98
  match self {
93
- InputKey::Local(local) => local.path.as_str(),
99
+ InputKey::Local(local) => local
100
+ .prefix
101
+ .as_ref()
102
+ .and_then(|pfx| local.given_path.strip_prefix(dbg!(pfx)).ok())
103
+ .unwrap_or_else(|| &local.given_path)
104
+ .as_str(),
94
105
  InputKey::Remote(remote) => remote.path.as_str(),
95
106
  }
96
107
  }
@@ -100,7 +111,7 @@ impl InputKey {
100
111
  // NOTE: Safe unwraps, since the presence of a filename component
101
112
  // is a construction invariant of all `InputKey` variants.
102
113
  match self {
103
- InputKey::Local(local) => local.path.file_name().unwrap(),
114
+ InputKey::Local(local) => local.given_path.file_name().unwrap(),
104
115
  InputKey::Remote(remote) => remote.path.file_name().unwrap(),
105
116
  }
106
117
  }
@@ -108,8 +119,6 @@ impl InputKey {
108
119
 
109
120
  pub(crate) struct InputRegistry {
110
121
  pub(crate) inputs: IndexMap<InputKey, AuditInput>,
111
- // pub(crate) actions: IndexMap<InputKey, Action>,
112
- // pub(crate) workflows: IndexMap<InputKey, Workflow>,
113
122
  }
114
123
 
115
124
  impl InputRegistry {
@@ -140,10 +149,14 @@ impl InputRegistry {
140
149
 
141
150
  /// Registers a workflow or action definition from its path on disk.
142
151
  #[instrument(skip(self))]
143
- pub(crate) fn register_by_path(&mut self, path: &Utf8Path) -> Result<()> {
144
- match Workflow::from_file(path) {
152
+ pub(crate) fn register_by_path(
153
+ &mut self,
154
+ path: &Utf8Path,
155
+ prefix: Option<&Utf8Path>,
156
+ ) -> Result<()> {
157
+ match Workflow::from_file(path, prefix) {
145
158
  Ok(workflow) => self.register_input(workflow.into()),
146
- Err(we) => match Action::from_file(path) {
159
+ Err(we) => match Action::from_file(path, prefix) {
147
160
  Ok(action) => self.register_input(action.into()),
148
161
  Err(ae) => Err(anyhow!("failed to register input as workflow or action"))
149
162
  .with_context(|| we)
@@ -289,8 +302,8 @@ mod tests {
289
302
  use super::InputKey;
290
303
 
291
304
  #[test]
292
- fn test_workflow_key_display() {
293
- let local = InputKey::local("/foo/bar/baz.yml".into()).unwrap();
305
+ fn test_input_key_display() {
306
+ let local = InputKey::local("/foo/bar/baz.yml", None).unwrap();
294
307
  assert_eq!(local.to_string(), "file:///foo/bar/baz.yml");
295
308
 
296
309
  // No ref
@@ -313,4 +326,26 @@ mod tests {
313
326
  "https://github.com/foo/bar/blob/v1/.github/workflows/baz.yml"
314
327
  );
315
328
  }
329
+
330
+ #[test]
331
+ fn test_input_key_local_path() {
332
+ let local = InputKey::local("/foo/bar/baz.yml", None).unwrap();
333
+ assert_eq!(local.best_effort_relative_path(), "/foo/bar/baz.yml");
334
+
335
+ let local = InputKey::local("/foo/bar/baz.yml", Some("/foo")).unwrap();
336
+ assert_eq!(local.best_effort_relative_path(), "bar/baz.yml");
337
+
338
+ let local = InputKey::local("/foo/bar/baz.yml", Some("/foo/bar/")).unwrap();
339
+ assert_eq!(local.best_effort_relative_path(), "baz.yml");
340
+
341
+ let local = InputKey::local(
342
+ "/home/runner/work/repo/repo/.github/workflows/baz.yml",
343
+ Some("/home/runner/work/repo/repo"),
344
+ )
345
+ .unwrap();
346
+ assert_eq!(
347
+ local.best_effort_relative_path(),
348
+ ".github/workflows/baz.yml"
349
+ );
350
+ }
316
351
  }
@@ -50,7 +50,11 @@ pub(crate) fn finding_snippet<'w>(
50
50
  Snippet::source(input.document().source())
51
51
  .fold(true)
52
52
  .line_start(1)
53
- .origin(input.link().unwrap_or(input_key.path()))
53
+ .origin(
54
+ input
55
+ .link()
56
+ .unwrap_or(input_key.best_effort_relative_path()),
57
+ )
54
58
  .annotations(locations.iter().map(|loc| {
55
59
  let annotation = match loc.symbolic.link {
56
60
  Some(ref link) => link,
@@ -125,7 +125,8 @@ fn build_locations<'a>(locations: impl Iterator<Item = &'a Location<'a>>) -> Vec
125
125
  PhysicalLocation::builder()
126
126
  .artifact_location(
127
127
  ArtifactLocation::builder()
128
- .uri(location.symbolic.key.path())
128
+ .uri_base_id("%SRCROOT%")
129
+ .uri(location.symbolic.key.best_effort_relative_path())
129
130
  .build(),
130
131
  )
131
132
  .region(