Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/zizmor-self.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ jobs:
security-events: write
contents: read
actions: read
secrets:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
pull-requests: write
73 changes: 50 additions & 23 deletions .github/workflows/zizmor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
name: zizmor

# Reusable workflow that audits the calling repository's GitHub Actions
# with zizmor (https://docs.zizmor.sh). Findings are annotated inline and
# summarised to Slack; SARIF upload to code scanning is opt-in.
# with zizmor (https://docs.zizmor.sh). Pull requests get a sticky summary
# comment on every repo; SARIF upload to code scanning is an opt-in extra
# that only takes effect on public repos, where it needs no Advanced
# Security license. Private repos fall back to inline annotations.

on:
workflow_call:
Expand All @@ -22,7 +24,7 @@
required: false
type: boolean
default: false
description: "Upload SARIF to GitHub code scanning; off by default to match the Slack-first flow of the other scanners"
description: "Upload SARIF to GitHub code scanning; only takes effect on public repos."
enforce:
required: false
type: boolean
Expand All @@ -33,14 +35,6 @@
type: string
default: medium
description: "Severity threshold used when enforce is true (low, medium or high)"
secrets:
SLACK_WEBHOOK_URL:
required: false
description: "If set, the severity summary is posted here when there are findings"
outputs:
slack_summary:
description: "A pre-formatted severity summary for Slack"
value: ${{ jobs.scan.outputs.slack_summary }}

permissions: {}

Expand All @@ -51,8 +45,7 @@
security-events: write # upload-sarif
contents: read # actions/checkout on private repos
actions: read # upload-sarif on private repos
outputs:
slack_summary: ${{ steps.summary.outputs.summary }}
pull-requests: write # sticky PR comment
env:
ZIZMOR_VERSION: ${{ inputs.zizmor_version }}
ZIZMOR_PERSONA: ${{ inputs.persona }}
Expand Down Expand Up @@ -111,28 +104,62 @@
echo "| Info | $INFO |"
} >> "$GITHUB_STEP_SUMMARY"

SUMMARY=":large_orange_circle: High: $HIGH :large_yellow_circle: Medium: $MEDIUM :white_circle: Low: $LOW ${{ github.repository }} (zizmor)"
{
echo "summary=$SUMMARY"
echo "high=$HIGH"
echo "medium=$MEDIUM"
echo "low=$LOW"
echo "info=$INFO"
echo "total=$TOTAL"
} >> "$GITHUB_OUTPUT"

- name: Notify Slack
- name: Comment on pull request
if: >-
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
SUMMARY: ${{ steps.summary.outputs.summary }}
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HIGH: ${{ steps.summary.outputs.high }}
MEDIUM: ${{ steps.summary.outputs.medium }}
LOW: ${{ steps.summary.outputs.low }}
INFO: ${{ steps.summary.outputs.info }}
TOTAL: ${{ steps.summary.outputs.total }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
if [ -z "$SLACK_WEBHOOK_URL" ] || [ "$TOTAL" = "0" ]; then
echo "Slack notification skipped (no webhook or no findings)"
exit 0
MARKER="<!-- zizmor-report -->"
if [ "$TOTAL" = "0" ]; then
BODY="$MARKER
## zizmor

:white_check_mark: No findings in this repository's workflows. ([run]($RUN_URL))"
else
BODY="$MARKER
## zizmor findings

| Severity | Count |
|----------|-------|
| High | $HIGH |
| Medium | $MEDIUM |
| Low | $LOW |
| Info | $INFO |

Full details are in the [workflow run]($RUN_URL)."
fi

Check warning on line 149 in .github/workflows/zizmor.yml

View check run for this annotation

probelabs / Visor: performance

performance Issue

The script fetches all comments on a pull request to find a specific one to update. On pull requests with a large number of comments, this can be slow and consume a high number of GitHub API calls due to pagination. The `jq` query `[.[] | ...]` is not streamable and forces `gh api --paginate` to fetch all pages of comments before filtering.
Raw output
Modify the `jq` query to use a streaming approach with `first(...)`. This allows `gh api` and `head -1` to stop processing as soon as the first matching comment is found, which will be significantly more performant on PRs with many comments. Replace `'[.[] | select(.body | startswith("<!-- zizmor-report -->"))][0].id // empty'` with `'first(.[] | select(.body | startswith("<!-- zizmor-report -->"))).id // empty'`.
COMMENT_ID=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --paginate \
--jq '[.[] | select(.body | startswith("<!-- zizmor-report -->"))][0].id // empty' \
| head -1)

if [ -n "$COMMENT_ID" ]; then
gh api -X PATCH "repos/$REPO/issues/comments/$COMMENT_ID" -f body="$BODY" > /dev/null
echo "updated comment $COMMENT_ID"
elif [ "$TOTAL" != "0" ]; then
gh api -X POST "repos/$REPO/issues/$PR_NUMBER/comments" -f body="$BODY" > /dev/null
echo "posted new comment"

Check warning on line 159 in .github/workflows/zizmor.yml

View check run for this annotation

probelabs / Visor: quality

architecture Issue

The shell script in the 'Comment on pull request' step does not use `set -e`. This can lead to unexpected behavior where the script continues to execute even after a command fails, making debugging difficult and the script less reliable.
Raw output
Add `set -e` at the beginning of the script to ensure it exits immediately if a command fails.
else

Check warning on line 160 in .github/workflows/zizmor.yml

View check run for this annotation

probelabs / Visor: architecture

architecture Issue

The shell script to find and update a pull request comment re-implements a common pattern that could be handled by a dedicated GitHub Action. While the current implementation using `gh api` is correct and avoids an external dependency, a declarative approach might be simpler to maintain.
Raw output
Consider using a pre-existing GitHub Action like `peter-evans/create-or-update-comment` to manage the PR comment. This would replace the multi-line shell script with a more declarative action, which can improve workflow readability and abstract away the implementation details of finding and updating comments. This is an alternative to consider, as the current approach is also valid.
echo "no findings and no existing comment, nothing to post"
fi
jq -n --arg text "$SUMMARY — $RUN_URL" '{text: $text}' \
| curl -sf -X POST -H 'Content-Type: application/json' -d @- "$SLACK_WEBHOOK_URL"

- name: Enforce threshold
if: ${{ inputs.enforce }}
Expand Down
Loading