This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Security Alerts Review | |
on: | |
push: | |
paths: | |
- "**/*.sol" | |
- ".github/workflows/securityAlertsReview.yml" | |
issue_comment: | |
types: | |
- created | |
- edited | |
pull_request: | |
types: | |
- ready_for_review | |
workflow_dispatch: | |
jobs: | |
check-security-alerts: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Fetch PR Number | |
id: fetch_pr | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
PR_NUMBER=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \ | |
"https://api.github.com/repos/${{ github.repository }}/pulls?state=open" | jq -r '.[0].number') | |
if [[ -z "$PR_NUMBER" || "$PR_NUMBER" == "null" ]]; then | |
echo "No open PR found, skipping check." | |
exit 0 | |
fi | |
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV | |
echo "PR number: $PR_NUMBER" | |
- name: Fetch Security Alerts for PR | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
echo "Fetching security alerts for PR #${PR_NUMBER}..." | |
ALERTS=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \ | |
"https://api.github.com/repos/${{ github.repository }}/code-scanning/alerts?pr=${PR_NUMBER}") | |
echo "Raw API Response: $ALERTS" | |
UNRESOLVED_ALERTS=$(echo "$ALERTS" | jq -c '[.[] | select(.state == "open")]' || echo "[]") | |
DISMISSED_WITH_COMMENTS=$(echo "$ALERTS" | jq -c '[.[] | select(.state == "dismissed" and (.dismissed_comment != null and .dismissed_comment != ""))]' || echo "[]") | |
DISMISSED_WITHOUT_COMMENTS=$(echo "$ALERTS" | jq -c '[.[] | select(.state == "dismissed" and (.dismissed_comment == null or .dismissed_comment == ""))]' || echo "[]") | |
UNRESOLVED_COUNT=$(echo "$UNRESOLVED_ALERTS" | jq -r 'length') | |
DISMISSED_WITH_COMMENTS_COUNT=$(echo "$DISMISSED_WITH_COMMENTS" | jq -r 'length') | |
DISMISSED_WITHOUT_COMMENTS_COUNT=$(echo "$DISMISSED_WITHOUT_COMMENTS" | jq -r 'length') | |
echo "UNRESOLVED_COUNT=$UNRESOLVED_COUNT" >> $GITHUB_ENV | |
echo "DISMISSED_WITH_COMMENTS_COUNT=$DISMISSED_WITH_COMMENTS_COUNT" >> $GITHUB_ENV | |
echo "DISMISSED_WITHOUT_COMMENTS_COUNT=$DISMISSED_WITHOUT_COMMENTS_COUNT" >> $GITHUB_ENV | |
- name: Post or Update PR Comment | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
COMMENT_BODY="### π€ GitHub Action: Security Alerts Review π\n" | |
# Unresolved Alerts | |
if [[ "$UNRESOLVED_COUNT" -gt 0 ]]; then | |
COMMENT_BODY+="\n## π¨ Unresolved Security Alerts\n" | |
COMMENT_BODY+="These **must be resolved** before merging:\n\n" | |
while IFS= read -r row; do | |
ALERT_URL=$(echo "$row" | jq -r '.html_url') | |
ALERT_FILE=$(echo "$row" | jq -r '.most_recent_instance.location.path') | |
ALERT_DESCRIPTION=$(echo "$row" | jq -r '.most_recent_instance.message.text') | |
COMMENT_BODY+="π΄ **[View Alert]($ALERT_URL)**\n" | |
COMMENT_BODY+="π **File:** \`$ALERT_FILE\`\n" | |
COMMENT_BODY+="π‘ **Issue:** $ALERT_DESCRIPTION\n\n" | |
done < <(echo "$UNRESOLVED_ALERTS" | jq -c '.[]') | |
COMMENT_BODY+="β οΈ **Please resolve these alerts before merging.**\n\n" | |
fi | |
# Dismissed Alerts With Comments | |
if [[ "$DISMISSED_WITH_COMMENTS_COUNT" -gt 0 ]]; then | |
COMMENT_BODY+="\n## β Dismissed Alerts with Explanations\n" | |
COMMENT_BODY+="The following alerts were **dismissed with valid reasons**:\n\n" | |
while IFS= read -r row; do | |
ALERT_URL=$(echo "$row" | jq -r '.html_url') | |
ALERT_FILE=$(echo "$row" | jq -r '.most_recent_instance.location.path') | |
ALERT_DESCRIPTION=$(echo "$row" | jq -r '.most_recent_instance.message.text') | |
DISMISS_REASON=$(echo "$row" | jq -r '.dismissed_reason') | |
DISMISS_COMMENT=$(echo "$row" | jq -r '.dismissed_comment') | |
FORMATTED_DISMISS_REASON=$(echo "$DISMISS_REASON" | awk '{print toupper(substr($0,1,1)) substr($0,2)}') | |
COMMENT_BODY+="π’ **[View Alert]($ALERT_URL)**\n" | |
COMMENT_BODY+="π **File:** \`$ALERT_FILE\`\n" | |
COMMENT_BODY+="π‘ **Issue:** $ALERT_DESCRIPTION\n" | |
COMMENT_BODY+="βοΈ **Dismissal Reason:** \`$FORMATTED_DISMISS_REASON\`\n" | |
COMMENT_BODY+="π¬ **Comment:** \"$DISMISS_COMMENT\"\n\n" | |
done < <(echo "$DISMISSED_WITH_COMMENTS" | jq -c '.[]') | |
COMMENT_BODY+="β **These alerts were reviewed and dismissed correctly.**\n\n" | |
fi | |
# Dismissed Alerts Without Comments | |
if [[ "$DISMISSED_WITHOUT_COMMENTS_COUNT" -gt 0 ]]; then | |
COMMENT_BODY+="\n## β οΈ Dismissed Alerts Without Comments\n" | |
COMMENT_BODY+="The following alerts were **dismissed without explanations**:\n\n" | |
while IFS= read -r row; do | |
ALERT_URL=$(echo "$row" | jq -r '.html_url') | |
ALERT_FILE=$(echo "$row" | jq -r '.most_recent_instance.location.path') | |
ALERT_DESCRIPTION=$(echo "$row" | jq -r '.most_recent_instance.message.text') | |
COMMENT_BODY+="β οΈ **[View Alert]($ALERT_URL)**\n" | |
COMMENT_BODY+="π **File:** \`$ALERT_FILE\`\n" | |
COMMENT_BODY+="π‘ **Issue:** $ALERT_DESCRIPTION\n\n" | |
done < <(echo "$DISMISSED_WITHOUT_COMMENTS" | jq -c '.[]') | |
COMMENT_BODY+="β οΈ **Please provide a dismissal reason for these alerts.**\n\n" | |
fi | |
echo "COMMENT_BODY" | |
echo $COMMENT_BODY | |
COMMENT_BODY_JSON=$(printf '%s' "$COMMENT_BODY" | jq -Rs .) | |
echo "COMMENT_BODY_JSON" | |
echo $COMMENT_BODY_JSON | |
if [[ -n "$EXISTING_COMMENT_ID" ]]; then | |
HTTP_RESPONSE=$(curl -s -o response.json -w "%{http_code}" -X PATCH \ | |
-H "Authorization: token ${GITHUB_TOKEN}" -H "Content-Type: application/json" \ | |
-d "{\"body\": $COMMENT_BODY_JSON}" \ | |
"https://api.github.com/repos/${{ github.repository }}/issues/comments/${EXISTING_COMMENT_ID}") | |
else | |
HTTP_RESPONSE=$(curl -s -o response.json -w "%{http_code}" -X POST \ | |
-H "Authorization: token ${GITHUB_TOKEN}" -H "Content-Type: application/json" \ | |
-d "{\"body\": $COMMENT_BODY_JSON}" \ | |
"https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/comments") | |
fi | |
if [[ "$HTTP_RESPONSE" -ne 200 && "$HTTP_RESPONSE" -ne 201 ]]; then | |
echo "β Error: Failed to update PR comment. HTTP Status: $HTTP_RESPONSE" | |
cat response.json | |
exit 1 | |
fi |